| Directory: | ./ |
|---|---|
| File: | storage/rocksdb/ha_rocksdb.cc |
| Date: | 2022-11-26 14:12:44 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 5538 | 6227 | 88.9% |
| Branches: | 5376 | 10837 | 49.6% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | Copyright (c) 2012, Monty Program Ab | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; version 2 of the License. | ||
| 7 | |||
| 8 | This program is distributed in the hope that it will be useful, | ||
| 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | GNU General Public License for more details. | ||
| 12 | |||
| 13 | You should have received a copy of the GNU General Public License | ||
| 14 | along with this program; if not, write to the Free Software | ||
| 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
| 16 | |||
| 17 | #ifdef USE_PRAGMA_IMPLEMENTATION | ||
| 18 | #pragma implementation // gcc: Class implementation | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #define MYSQL_SERVER 1 | ||
| 22 | |||
| 23 | /* The C++ file's header */ | ||
| 24 | #include "./ha_rocksdb.h" | ||
| 25 | |||
| 26 | #ifdef TARGET_OS_LINUX | ||
| 27 | #include <errno.h> | ||
| 28 | #include <sys/resource.h> | ||
| 29 | #include <sys/syscall.h> | ||
| 30 | #include <sys/types.h> | ||
| 31 | #endif | ||
| 32 | |||
| 33 | /* C++ standard header files */ | ||
| 34 | #include <inttypes.h> | ||
| 35 | #include <algorithm> | ||
| 36 | #include <deque> | ||
| 37 | #include <limits> | ||
| 38 | #include <map> | ||
| 39 | #include <queue> | ||
| 40 | #include <set> | ||
| 41 | #include <string> | ||
| 42 | #include <vector> | ||
| 43 | |||
| 44 | /* MySQL includes */ | ||
| 45 | #include "my_bit.h" | ||
| 46 | #include "my_stacktrace.h" | ||
| 47 | #include "my_sys.h" | ||
| 48 | #include "mysql/thread_pool_priv.h" | ||
| 49 | #include "mysys_err.h" | ||
| 50 | #include "scope_guard.h" | ||
| 51 | #include "sql/debug_sync.h" | ||
| 52 | #include "sql-common/json_dom.h" | ||
| 53 | #include "sql/mysqld.h" | ||
| 54 | #include "sql/sql_audit.h" | ||
| 55 | #include "sql/sql_lex.h" | ||
| 56 | #include "sql/sql_partition.h" | ||
| 57 | #include "sql/sql_table.h" | ||
| 58 | #include "sql/sql_thd_internal_api.h" | ||
| 59 | #include "sql/table.h" | ||
| 60 | |||
| 61 | /* RocksDB includes */ | ||
| 62 | #include "monitoring/histogram.h" | ||
| 63 | #include "rocksdb/compaction_filter.h" | ||
| 64 | #include "rocksdb/compaction_job_stats.h" | ||
| 65 | #include "rocksdb/env.h" | ||
| 66 | #include "rocksdb/env/composite_env_wrapper.h" | ||
| 67 | #include "rocksdb/memory_allocator.h" | ||
| 68 | #include "rocksdb/persistent_cache.h" | ||
| 69 | #include "rocksdb/rate_limiter.h" | ||
| 70 | #include "rocksdb/slice_transform.h" | ||
| 71 | #include "rocksdb/thread_status.h" | ||
| 72 | #include "rocksdb/trace_reader_writer.h" | ||
| 73 | #include "rocksdb/utilities/checkpoint.h" | ||
| 74 | #include "rocksdb/utilities/convenience.h" | ||
| 75 | #include "rocksdb/utilities/fault_injection_fs.h" | ||
| 76 | #include "rocksdb/utilities/memory_util.h" | ||
| 77 | #include "rocksdb/utilities/sim_cache.h" | ||
| 78 | #include "rocksdb/utilities/write_batch_with_index.h" | ||
| 79 | #include "util/stop_watch.h" | ||
| 80 | |||
| 81 | /* MyRocks includes */ | ||
| 82 | #include "./event_listener.h" | ||
| 83 | #include "./ha_rocksdb_proto.h" | ||
| 84 | #include "./ha_rockspart.h" | ||
| 85 | #include "./logger.h" | ||
| 86 | #include "./rdb_cf_manager.h" | ||
| 87 | #include "./rdb_cf_options.h" | ||
| 88 | #include "./rdb_converter.h" | ||
| 89 | #include "./rdb_datadic.h" | ||
| 90 | #include "./rdb_i_s.h" | ||
| 91 | #include "./rdb_index_merge.h" | ||
| 92 | #include "./rdb_iterator.h" | ||
| 93 | #include "./rdb_mutex_wrapper.h" | ||
| 94 | #include "./rdb_psi.h" | ||
| 95 | #include "./rdb_threads.h" | ||
| 96 | |||
| 97 | #ifdef RAPIDJSON_NO_SIZETYPEDEFINE | ||
| 98 | // if we build within the server, it will set RAPIDJSON_NO_SIZETYPEDEFINE | ||
| 99 | // globally and require to include my_rapidjson_size_t.h | ||
| 100 | #include "my_rapidjson_size_t.h" | ||
| 101 | #endif | ||
| 102 | #include <rapidjson/document.h> | ||
| 103 | |||
| 104 | #ifdef FB_HAVE_WSENV | ||
| 105 | #include "./ObjectFactory.h" | ||
| 106 | #endif | ||
| 107 | |||
| 108 | // MySQL 8.0 logger service interface | ||
| 109 | static SERVICE_TYPE(registry) *reg_srv = nullptr; | ||
| 110 | SERVICE_TYPE(log_builtins) *log_bi = nullptr; | ||
| 111 | SERVICE_TYPE(log_builtins_string) *log_bs = nullptr; | ||
| 112 | |||
| 113 | namespace myrocks { | ||
| 114 | |||
| 115 | static st_global_stats global_stats; | ||
| 116 | static st_export_stats export_stats; | ||
| 117 | static st_memory_stats memory_stats; | ||
| 118 | static st_io_stall_stats io_stall_stats; | ||
| 119 | Rdb_compaction_stats compaction_stats; | ||
| 120 | |||
| 121 | const std::string DEFAULT_CF_NAME("default"); | ||
| 122 | const std::string DEFAULT_SYSTEM_CF_NAME("__system__"); | ||
| 123 | const std::string DEFAULT_TMP_CF_NAME("__tmp__"); | ||
| 124 | const std::string DEFAULT_TMP_SYSTEM_CF_NAME("__tmp_system__"); | ||
| 125 | const std::string PER_INDEX_CF_NAME("$per_index_cf"); | ||
| 126 | const std::string DEFAULT_SK_CF_NAME("default_sk"); | ||
| 127 | const std::string TRUNCATE_TABLE_PREFIX("#truncate_tmp#"); | ||
| 128 | const std::string TMP_SCHEMA_NAME("#sqltmp"); | ||
| 129 | |||
| 130 | static std::vector<std::string> rdb_tables_to_recalc; | ||
| 131 | |||
| 132 | static Rdb_exec_time st_rdb_exec_time; | ||
| 133 | |||
| 134 | int mysql_value_to_bool(struct st_mysql_value *value, bool *return_value); | ||
| 135 | |||
| 136 | /** | ||
| 137 | Updates row counters based on the table type and operation type. | ||
| 138 | */ | ||
| 139 | 257309685 | void ha_rocksdb::update_row_stats(const operation_type &type, ulonglong count) { | |
| 140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 257309685 times.
|
257309685 | assert(type < ROWS_MAX); |
| 141 | // Find if we are modifying system databases. | ||
| 142 |
3/4✓ Branch 0 taken 257321022 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 257321004 times.
|
257309685 | if (table->s && m_tbl_def->m_is_mysql_system_table) { |
| 143 | 18 | global_stats.system_rows[type].add(count); | |
| 144 | } else { | ||
| 145 | 257309667 | global_stats.rows[type].add(count); | |
| 146 | } | ||
| 147 | 257351031 | } | |
| 148 | |||
| 149 | ✗ | void ha_rocksdb::update_row_read(ulonglong count) { | |
| 150 | ✗ | update_row_stats(ROWS_READ, count); | |
| 151 | } | ||
| 152 | |||
| 153 | 40349069 | void ha_rocksdb::inc_covered_sk_lookup() { | |
| 154 | 40349069 | global_stats.covered_secondary_key_lookups.inc(); | |
| 155 | 40349069 | } | |
| 156 | |||
| 157 | void dbug_dump_database(rocksdb::DB *db); | ||
| 158 | static handler *rocksdb_create_handler(my_core::handlerton *hton, | ||
| 159 | my_core::TABLE_SHARE *table_arg, | ||
| 160 | bool partitioned, | ||
| 161 | my_core::MEM_ROOT *mem_root); | ||
| 162 | |||
| 163 | 27839 | static rocksdb::CompactRangeOptions getCompactRangeOptions( | |
| 164 | int concurrency = 0, | ||
| 165 | rocksdb::BottommostLevelCompaction bottommost_level_compaction = | ||
| 166 | rocksdb::BottommostLevelCompaction::kForceOptimized) { | ||
| 167 | 27839 | rocksdb::CompactRangeOptions compact_range_options; | |
| 168 | 27839 | compact_range_options.bottommost_level_compaction = | |
| 169 | bottommost_level_compaction; | ||
| 170 | 27839 | compact_range_options.exclusive_manual_compaction = false; | |
| 171 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 27827 times.
|
27839 | if (concurrency > 0) { |
| 172 | 12 | compact_range_options.max_subcompactions = concurrency; | |
| 173 | } | ||
| 174 | 27839 | return compact_range_options; | |
| 175 | } | ||
| 176 | |||
| 177 | /////////////////////////////////////////////////////////// | ||
| 178 | // Parameters and settings | ||
| 179 | /////////////////////////////////////////////////////////// | ||
| 180 | static char *rocksdb_default_cf_options = nullptr; | ||
| 181 | static char *rocksdb_override_cf_options = nullptr; | ||
| 182 | static char *rocksdb_update_cf_options = nullptr; | ||
| 183 | static bool rocksdb_use_default_sk_cf = false; | ||
| 184 | static bool rocksdb_allow_unsafe_alter = false; | ||
| 185 | |||
| 186 | /////////////////////////////////////////////////////////// | ||
| 187 | // Globals | ||
| 188 | /////////////////////////////////////////////////////////// | ||
| 189 | handlerton *rocksdb_hton; | ||
| 190 | |||
| 191 | rocksdb::TransactionDB *rdb = nullptr; | ||
| 192 | rocksdb::HistogramImpl *commit_latency_stats = nullptr; | ||
| 193 | |||
| 194 | static std::shared_ptr<rocksdb::Statistics> rocksdb_stats; | ||
| 195 | static std::shared_ptr<Rdb_tbl_prop_coll_factory> properties_collector_factory; | ||
| 196 | |||
| 197 | Rdb_dict_manager_selector dict_manager; | ||
| 198 | Rdb_cf_manager cf_manager; | ||
| 199 | Rdb_ddl_manager ddl_manager; | ||
| 200 | Rdb_hton_init_state hton_init_state; | ||
| 201 | |||
| 202 | /** | ||
| 203 | MyRocks background thread control | ||
| 204 | N.B. This is besides RocksDB's own background threads | ||
| 205 | (@see rocksdb::CancelAllBackgroundWork()) | ||
| 206 | */ | ||
| 207 | |||
| 208 | static Rdb_background_thread rdb_bg_thread; | ||
| 209 | |||
| 210 | static Rdb_index_stats_thread rdb_is_thread; | ||
| 211 | |||
| 212 | static Rdb_manual_compaction_thread rdb_mc_thread; | ||
| 213 | |||
| 214 | static Rdb_drop_index_thread rdb_drop_idx_thread; | ||
| 215 | // List of table names (using regex) that are exceptions to the strict | ||
| 216 | // collation check requirement. | ||
| 217 | Regex_list_handler *rdb_collation_exceptions; | ||
| 218 | |||
| 219 | static const char *rdb_get_error_messages(int error); | ||
| 220 | |||
| 221 | 1973 | static void rocksdb_flush_all_memtables() { | |
| 222 | 1973 | const Rdb_cf_manager &cf_manager = rdb_get_cf_manager(); | |
| 223 | |||
| 224 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1940 times.
|
1973 | if (!cf_manager.is_initialized()) return; |
| 225 | |||
| 226 | // RocksDB will fail the flush if the CF is deleted, | ||
| 227 | // but here we don't handle return status | ||
| 228 |
3/4✓ Branch 0 taken 1940 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7543 times.
✓ Branch 3 taken 1940 times.
|
9483 | for (const auto &cf_handle : cf_manager.get_all_cf()) { |
| 229 |
1/2✓ Branch 0 taken 7543 times.
✗ Branch 1 not taken.
|
7543 | rdb->Flush(rocksdb::FlushOptions(), cf_handle.get()); |
| 230 | 1940 | } | |
| 231 | } | ||
| 232 | |||
| 233 | 39 | static void rocksdb_delete_column_family_stub(THD *const /* thd */, | |
| 234 | struct SYS_VAR *const /* var */, | ||
| 235 | void *const /* var_ptr */, | ||
| 236 | 39 | const void *const /* save */) {} | |
| 237 | |||
| 238 | 55 | static int rocksdb_delete_column_family(THD *const /* thd */, | |
| 239 | struct SYS_VAR *const /* var */, | ||
| 240 | void *const /* var_ptr */, | ||
| 241 | struct st_mysql_value *const value) { | ||
| 242 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
|
55 | assert(value != nullptr); |
| 243 | |||
| 244 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 245 | 55 | int len = sizeof(buff); | |
| 246 | |||
| 247 |
1/2✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
|
55 | const char *const cf = value->val_str(value, buff, &len); |
| 248 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 54 times.
|
55 | if (cf == nullptr) return HA_EXIT_SUCCESS; |
| 249 | |||
| 250 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | std::string cf_name = std::string(cf); |
| 251 | // Forbid to remove these built-in CFs | ||
| 252 |
4/4✓ Branch 0 taken 52 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 1 times.
|
159 | if (cf_name == DEFAULT_SYSTEM_CF_NAME || cf_name == DEFAULT_CF_NAME || |
| 253 |
6/6✓ Branch 0 taken 53 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 48 times.
|
162 | cf_name.empty() || |
| 254 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
54 | (cf_name == DEFAULT_SK_CF_NAME && rocksdb_use_default_sk_cf)) { |
| 255 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_CANT_DROP_CF, MYF(0), cf); |
| 256 | 6 | return HA_EXIT_FAILURE; | |
| 257 | } | ||
| 258 | |||
| 259 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | auto &cf_manager = rdb_get_cf_manager(); |
| 260 | 48 | int ret = 0; | |
| 261 | |||
| 262 | { | ||
| 263 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | auto local_dict_manager = dict_manager.get_dict_manager_selector_non_const( |
| 264 | false /*is_tmp_table*/); | ||
| 265 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 266 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | ret = cf_manager.drop_cf(&ddl_manager, local_dict_manager, cf_name); |
| 267 | 48 | } | |
| 268 | |||
| 269 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 10 times.
|
48 | if (ret == HA_EXIT_SUCCESS) { |
| 270 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | rdb_drop_idx_thread.signal(); |
| 271 | } else { | ||
| 272 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | my_error(ER_CANT_DROP_CF, MYF(0), cf); |
| 273 | } | ||
| 274 | |||
| 275 | 48 | return ret; | |
| 276 | 54 | } | |
| 277 | |||
| 278 | /////////////////////////////////////////////////////////// | ||
| 279 | // Hash map: table name => open table handler | ||
| 280 | /////////////////////////////////////////////////////////// | ||
| 281 | |||
| 282 | namespace // anonymous namespace = not visible outside this source file | ||
| 283 | { | ||
| 284 | |||
| 285 | class Rdb_open_tables_map { | ||
| 286 | private: | ||
| 287 | /* Hash table used to track the handlers of open tables */ | ||
| 288 | std::unordered_map<std::string, Rdb_table_handler *> m_table_map; | ||
| 289 | |||
| 290 | /* The mutex used to protect the hash table */ | ||
| 291 | mutable Rds_mysql_mutex m_mutex; | ||
| 292 | |||
| 293 | public: | ||
| 294 | 932 | void init() { | |
| 295 | 932 | m_table_map.clear(); | |
| 296 | 932 | m_mutex.init(rdb_psi_open_tbls_mutex_key, MY_MUTEX_INIT_FAST); | |
| 297 | 932 | } | |
| 298 | |||
| 299 | 929 | void free() { | |
| 300 | 929 | m_table_map.clear(); | |
| 301 | 929 | m_mutex.destroy(); | |
| 302 | 929 | } | |
| 303 | |||
| 304 | 899 | size_t count() { return m_table_map.size(); } | |
| 305 | |||
| 306 | Rdb_table_handler *get_table_handler(const char *const table_name); | ||
| 307 | void release_table_handler(Rdb_table_handler *const table_handler); | ||
| 308 | |||
| 309 | std::vector<std::string> get_table_names(void) const; | ||
| 310 | }; | ||
| 311 | |||
| 312 | } // anonymous namespace | ||
| 313 | |||
| 314 | static Rdb_open_tables_map rdb_open_tables; | ||
| 315 | |||
| 316 | 10 | static std::string rdb_normalize_dir(std::string dir) { | |
| 317 |
6/6✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 10 times.
|
12 | while (dir.size() > 0 && dir.back() == '/') { |
| 318 | 2 | dir.resize(dir.size() - 1); | |
| 319 | } | ||
| 320 | 10 | return dir; | |
| 321 | } | ||
| 322 | |||
| 323 | 7 | static int rocksdb_create_checkpoint(const char *checkpoint_dir_raw) { | |
| 324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(checkpoint_dir_raw); |
| 325 | |||
| 326 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
14 | const auto checkpoint_dir = rdb_normalize_dir(checkpoint_dir_raw); |
| 327 |
9/18✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 17 not taken.
|
7 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 328 | "creating checkpoint in directory: %s\n", | ||
| 329 | checkpoint_dir.c_str()); | ||
| 330 | rocksdb::Checkpoint *checkpoint; | ||
| 331 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | auto status = rocksdb::Checkpoint::Create(rdb, &checkpoint); |
| 332 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | if (status.ok()) { |
| 333 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | status = checkpoint->CreateCheckpoint(checkpoint_dir.c_str()); |
| 334 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | delete checkpoint; |
| 335 |
3/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
|
7 | if (status.ok()) { |
| 336 |
9/18✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
|
5 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 337 | "created checkpoint in directory: %s\n", | ||
| 338 | checkpoint_dir.c_str()); | ||
| 339 | 5 | return HA_EXIT_SUCCESS; | |
| 340 | } else { | ||
| 341 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | my_error(ER_GET_ERRMSG, MYF(0), status.code(), status.ToString().c_str(), |
| 342 | rocksdb_hton_name); | ||
| 343 | } | ||
| 344 | } else { | ||
| 345 | ✗ | my_error(ER_GET_ERRMSG, MYF(0), status.code(), status.ToString().c_str(), | |
| 346 | rocksdb_hton_name); | ||
| 347 | } | ||
| 348 | |||
| 349 | 2 | return HA_EXIT_FAILURE; | |
| 350 | 7 | } | |
| 351 | |||
| 352 | 3 | static int rocksdb_remove_checkpoint(const char *checkpoint_dir_raw) { | |
| 353 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | const auto checkpoint_dir = rdb_normalize_dir(checkpoint_dir_raw); |
| 354 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 355 | "deleting temporary checkpoint in directory : %s\n", | ||
| 356 | checkpoint_dir.c_str()); | ||
| 357 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | const auto status = rocksdb::DestroyDB(checkpoint_dir, rocksdb::Options()); |
| 358 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (status.ok()) { |
| 359 | 3 | return HA_EXIT_SUCCESS; | |
| 360 | } | ||
| 361 | ✗ | my_error(ER_GET_ERRMSG, MYF(0), status.code(), status.ToString().c_str(), | |
| 362 | rocksdb_hton_name); | ||
| 363 | ✗ | return HA_EXIT_FAILURE; | |
| 364 | 3 | } | |
| 365 | |||
| 366 | 3 | static int rocksdb_create_checkpoint_validate( | |
| 367 | THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 368 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 369 | void *const save MY_ATTRIBUTE((__unused__)), | ||
| 370 | struct st_mysql_value *const value) { | ||
| 371 | char buf[FN_REFLEN]; | ||
| 372 | 3 | int len = sizeof(buf); | |
| 373 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | const char *const checkpoint_dir_raw = value->val_str(value, buf, &len); |
| 374 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (checkpoint_dir_raw) { |
| 375 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | return rocksdb_create_checkpoint(checkpoint_dir_raw); |
| 376 | } | ||
| 377 | ✗ | return HA_EXIT_FAILURE; | |
| 378 | } | ||
| 379 | |||
| 380 | /* This method is needed to indicate that the | ||
| 381 | ROCKSDB_CREATE_CHECKPOINT command is not read-only */ | ||
| 382 | 4 | static void rocksdb_create_checkpoint_update(THD *const thd, | |
| 383 | struct SYS_VAR *const var, | ||
| 384 | void *const var_ptr, | ||
| 385 | 4 | const void *const save) {} | |
| 386 | |||
| 387 | static int rocksdb_create_temporary_checkpoint_validate( | ||
| 388 | THD *const thd, struct SYS_VAR *const var, void *const save, | ||
| 389 | struct st_mysql_value *const value); | ||
| 390 | |||
| 391 | static void rocksdb_disable_file_deletions_update( | ||
| 392 | my_core::THD *const thd, my_core::SYS_VAR *const /* unused */, | ||
| 393 | void *const var_ptr, const void *const save); | ||
| 394 | |||
| 395 | static void rocksdb_max_compaction_history_update( | ||
| 396 | my_core::THD *const thd, my_core::SYS_VAR *const /* unused */, | ||
| 397 | void *const var_ptr, const void *const save); | ||
| 398 | |||
| 399 | static bool parse_fault_injection_params(bool *retryable, | ||
| 400 | uint32_t *failure_ratio, | ||
| 401 | std::vector<rocksdb::FileType> *types); | ||
| 402 | |||
| 403 | 1070 | static void rocksdb_force_flush_memtable_now_stub( | |
| 404 | THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 405 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 406 | void *const var_ptr MY_ATTRIBUTE((__unused__)), | ||
| 407 | 1070 | const void *const save MY_ATTRIBUTE((__unused__))) {} | |
| 408 | |||
| 409 | 1070 | static int rocksdb_force_flush_memtable_now( | |
| 410 | THD *const thd, struct SYS_VAR *const var, void *const var_ptr, | ||
| 411 | struct st_mysql_value *const value) { | ||
| 412 | 1070 | bool parsed_value = false; | |
| 413 |
6/8✓ Branch 0 taken 1070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1070 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1067 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1067 times.
|
1070 | if (mysql_value_to_bool(value, &parsed_value) != 0 || !parsed_value) { |
| 414 | 3 | return 1; | |
| 415 | } | ||
| 416 | |||
| 417 |
9/18✓ Branch 0 taken 1067 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1067 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1067 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1067 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1067 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1067 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1067 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1067 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1067 times.
✗ Branch 17 not taken.
|
1067 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Manual memtable flush."); |
| 418 |
1/2✓ Branch 0 taken 1067 times.
✗ Branch 1 not taken.
|
1067 | rocksdb_flush_all_memtables(); |
| 419 | 1067 | return HA_EXIT_SUCCESS; | |
| 420 | } | ||
| 421 | |||
| 422 | 10 | static void rocksdb_force_flush_memtable_and_lzero_now_stub( | |
| 423 | THD *const thd, struct SYS_VAR *const var, void *const var_ptr, | ||
| 424 | 10 | const void *const save) {} | |
| 425 | |||
| 426 | 7 | static int rocksdb_force_flush_memtable_and_lzero_now( | |
| 427 | THD *const thd, struct SYS_VAR *const var, void *const var_ptr, | ||
| 428 | struct st_mysql_value *const value) { | ||
| 429 |
9/18✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 17 not taken.
|
7 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Manual memtable and L0 flush."); |
| 430 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | rocksdb_flush_all_memtables(); |
| 431 | |||
| 432 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | const Rdb_cf_manager &cf_manager = rdb_get_cf_manager(); |
| 433 | 7 | rocksdb::CompactionOptions c_options = rocksdb::CompactionOptions(); | |
| 434 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | rocksdb::ColumnFamilyMetaData metadata; |
| 435 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | rocksdb::ColumnFamilyDescriptor cf_descr; |
| 436 | |||
| 437 | static constexpr int max_attempts = 3; | ||
| 438 | 7 | int i, num_errors = 0; | |
| 439 | |||
| 440 |
3/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 7 times.
|
39 | for (const auto &cf_handle : cf_manager.get_all_cf()) { |
| 441 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | for (i = 0; i < max_attempts; i++) { |
| 442 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | rdb->GetColumnFamilyMetaData(cf_handle.get(), &metadata); |
| 443 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | cf_handle->GetDescriptor(&cf_descr); |
| 444 | 36 | c_options.output_file_size_limit = cf_descr.options.target_file_size_base; | |
| 445 | |||
| 446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | assert(metadata.levels[0].level == 0); |
| 447 | 36 | std::vector<std::string> file_names; | |
| 448 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
|
54 | for (const auto &file : metadata.levels[0].files) { |
| 449 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | file_names.emplace_back(file.db_path + file.name); |
| 450 | } | ||
| 451 | |||
| 452 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 7 times.
|
36 | if (file_names.empty()) { |
| 453 | 29 | break; | |
| 454 | } | ||
| 455 | |||
| 456 | 7 | rocksdb::Status s; | |
| 457 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | s = rdb->CompactFiles(c_options, cf_handle.get(), file_names, 1); |
| 458 | |||
| 459 |
3/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4 times.
|
7 | if (!s.ok()) { |
| 460 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 461 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | cf_manager.get_cf(cf_handle->GetID()); |
| 462 | |||
| 463 | // If the CF handle has been removed from cf_manager, it is not an | ||
| 464 | // error. We are done with this CF and proceed to the next CF. | ||
| 465 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!cfh) { |
| 466 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 467 | "cf %s has been dropped during CompactFiles.", | ||
| 468 | cf_handle->GetName().c_str()); | ||
| 469 | ✗ | break; | |
| 470 | } | ||
| 471 | |||
| 472 | // Due to a race, it's possible for CompactFiles to collide | ||
| 473 | // with auto compaction, causing an error to return | ||
| 474 | // regarding file not found. In that case, retry. | ||
| 475 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (s.IsInvalidArgument()) { |
| 476 | ✗ | continue; | |
| 477 | } | ||
| 478 | |||
| 479 |
5/10✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
3 | if (!s.ok() && !s.IsAborted()) { |
| 480 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_GENERAL); | |
| 481 | ✗ | return HA_EXIT_FAILURE; | |
| 482 | } | ||
| 483 | 3 | break; | |
| 484 |
1/3✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
3 | } |
| 485 |
4/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
39 | } |
| 486 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (i == max_attempts) { |
| 487 | ✗ | num_errors++; | |
| 488 | } | ||
| 489 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | } |
| 490 | |||
| 491 | 7 | return num_errors == 0 ? HA_EXIT_SUCCESS : HA_EXIT_FAILURE; | |
| 492 | 7 | } | |
| 493 | |||
| 494 | 16 | static void rocksdb_cancel_manual_compactions_stub( | |
| 495 | THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 496 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 497 | void *const var_ptr MY_ATTRIBUTE((__unused__)), | ||
| 498 | 16 | const void *const save MY_ATTRIBUTE((__unused__))) {} | |
| 499 | |||
| 500 | 13 | static int rocksdb_cancel_manual_compactions( | |
| 501 | THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 502 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 503 | void *const var_ptr MY_ATTRIBUTE((__unused__)), | ||
| 504 | struct st_mysql_value *const value MY_ATTRIBUTE((__unused__))) { | ||
| 505 | 13 | rdb_mc_thread.cancel_all_pending_manual_compaction_requests(); | |
| 506 | // NO_LINT_DEBUG | ||
| 507 |
8/16✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 13 times.
✗ Branch 15 not taken.
|
13 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 508 | "RocksDB: Stopping all Manual Compactions."); | ||
| 509 | 13 | rdb->GetBaseDB()->DisableManualCompaction(); | |
| 510 | // NO_LINT_DEBUG | ||
| 511 |
8/16✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 13 times.
✗ Branch 15 not taken.
|
13 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 512 | "RocksDB: Enabling Manual Compactions."); | ||
| 513 | 13 | rdb->GetBaseDB()->EnableManualCompaction(); | |
| 514 | 13 | return HA_EXIT_SUCCESS; | |
| 515 | } | ||
| 516 | |||
| 517 | static void rocksdb_drop_index_wakeup_thread( | ||
| 518 | my_core::THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 519 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 520 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save); | ||
| 521 | |||
| 522 | static bool rocksdb_pause_background_work = false; | ||
| 523 | static Rds_mysql_mutex rdb_sysvars_mutex; | ||
| 524 | static Rds_mysql_mutex rdb_block_cache_resize_mutex; | ||
| 525 | static Rds_mysql_mutex rdb_bottom_pri_background_compactions_resize_mutex; | ||
| 526 | |||
| 527 | 106 | static void rocksdb_set_pause_background_work( | |
| 528 | my_core::THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 529 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 530 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 531 | 106 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 532 | 106 | const bool pause_requested = *static_cast<const bool *>(save); | |
| 533 |
2/2✓ Branch 0 taken 92 times.
✓ Branch 1 taken 14 times.
|
106 | if (rocksdb_pause_background_work != pause_requested) { |
| 534 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 46 times.
|
92 | if (pause_requested) { |
| 535 | 46 | rdb->PauseBackgroundWork(); | |
| 536 | } else { | ||
| 537 | 46 | rdb->ContinueBackgroundWork(); | |
| 538 | } | ||
| 539 | 92 | rocksdb_pause_background_work = pause_requested; | |
| 540 | } | ||
| 541 | 106 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 542 | 106 | } | |
| 543 | |||
| 544 | static void rocksdb_set_compaction_options(THD *thd, struct SYS_VAR *var, | ||
| 545 | void *var_ptr, const void *save); | ||
| 546 | |||
| 547 | static void rocksdb_set_table_stats_sampling_pct(THD *thd, struct SYS_VAR *var, | ||
| 548 | void *var_ptr, | ||
| 549 | const void *save); | ||
| 550 | |||
| 551 | static void rocksdb_update_table_stats_use_table_scan( | ||
| 552 | THD *const /* thd */, struct SYS_VAR *const /* var */, void *const var_ptr, | ||
| 553 | const void *const save); | ||
| 554 | |||
| 555 | static int rocksdb_index_stats_thread_renice( | ||
| 556 | THD *const /* thd */, struct SYS_VAR *const /* var */, void *const save, | ||
| 557 | struct st_mysql_value *const value); | ||
| 558 | |||
| 559 | static void rocksdb_set_rate_limiter_bytes_per_sec(THD *thd, | ||
| 560 | struct SYS_VAR *var, | ||
| 561 | void *var_ptr, | ||
| 562 | const void *save); | ||
| 563 | |||
| 564 | static void rocksdb_set_sst_mgr_rate_bytes_per_sec(THD *thd, | ||
| 565 | struct SYS_VAR *var, | ||
| 566 | void *var_ptr, | ||
| 567 | const void *save); | ||
| 568 | |||
| 569 | static void rocksdb_set_delayed_write_rate(THD *thd, struct SYS_VAR *var, | ||
| 570 | void *var_ptr, const void *save); | ||
| 571 | |||
| 572 | static void rocksdb_set_max_latest_deadlocks(THD *thd, struct SYS_VAR *var, | ||
| 573 | void *var_ptr, const void *save); | ||
| 574 | |||
| 575 | static void rdb_set_collation_exception_list(const char *exception_list); | ||
| 576 | static void rocksdb_set_collation_exception_list(THD *thd, struct SYS_VAR *var, | ||
| 577 | void *var_ptr, | ||
| 578 | const void *save); | ||
| 579 | |||
| 580 | static int rocksdb_validate_update_cf_options(THD *thd, struct SYS_VAR *var, | ||
| 581 | void *save, | ||
| 582 | st_mysql_value *value); | ||
| 583 | |||
| 584 | static void rocksdb_set_update_cf_options(THD *thd, struct SYS_VAR *var, | ||
| 585 | void *var_ptr, const void *save); | ||
| 586 | |||
| 587 | static int rocksdb_check_bulk_load( | ||
| 588 | THD *const thd, struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 589 | struct st_mysql_value *value); | ||
| 590 | |||
| 591 | static int rocksdb_check_bulk_load_allow_unsorted( | ||
| 592 | THD *const thd, struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 593 | struct st_mysql_value *value); | ||
| 594 | |||
| 595 | static void rocksdb_set_max_background_jobs(THD *thd, struct SYS_VAR *const var, | ||
| 596 | void *const var_ptr, | ||
| 597 | const void *const save); | ||
| 598 | static void rocksdb_set_max_background_compactions(THD *thd, | ||
| 599 | struct SYS_VAR *const var, | ||
| 600 | void *const var_ptr, | ||
| 601 | const void *const save); | ||
| 602 | |||
| 603 | static void rocksdb_set_bytes_per_sync(THD *thd, struct SYS_VAR *const var, | ||
| 604 | void *const var_ptr, | ||
| 605 | const void *const save); | ||
| 606 | static void rocksdb_set_wal_bytes_per_sync(THD *thd, struct SYS_VAR *const var, | ||
| 607 | void *const var_ptr, | ||
| 608 | const void *const save); | ||
| 609 | static int rocksdb_validate_set_block_cache_size(THD *thd, | ||
| 610 | struct SYS_VAR *const var, | ||
| 611 | void *var_ptr, | ||
| 612 | struct st_mysql_value *value); | ||
| 613 | static int rocksdb_tracing(THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 614 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 615 | void *const save, struct st_mysql_value *const value, | ||
| 616 | bool trace_block_cache_access = true); | ||
| 617 | static int rocksdb_validate_max_bottom_pri_background_compactions( | ||
| 618 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 619 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), void *var_ptr, | ||
| 620 | struct st_mysql_value *value); | ||
| 621 | ////////////////////////////////////////////////////////////////////////////// | ||
| 622 | // Options definitions | ||
| 623 | ////////////////////////////////////////////////////////////////////////////// | ||
| 624 | static const constexpr ulong RDB_MAX_LOCK_WAIT_SECONDS = 1024 * 1024 * 1024; | ||
| 625 | static const constexpr ulong RDB_MAX_ROW_LOCKS = 1024 * 1024 * 1024; | ||
| 626 | static const constexpr ulong RDB_DEFAULT_ROW_LOCKS = 1024 * 1024; | ||
| 627 | static const constexpr ulong RDB_DEFAULT_BULK_LOAD_SIZE = 1000; | ||
| 628 | static const constexpr int RDB_DEFAULT_MAX_BACKGROUND_JOBS = 2; | ||
| 629 | static const constexpr ulong RDB_DEFAULT_BLOCK_SIZE = 0x4000; // 16K | ||
| 630 | static const constexpr ulong RDB_DEFAULT_MAX_TOTAL_WAL_SIZE = | ||
| 631 | 0x80000000; // 2GB | ||
| 632 | static const constexpr ulong RDB_DEFAULT_TABLE_CACHE_NUMSHARDBITS = 6; | ||
| 633 | static const constexpr ulong RDB_MAX_BULK_LOAD_SIZE = 1024 * 1024 * 1024; | ||
| 634 | static const constexpr size_t RDB_DEFAULT_MERGE_BUF_SIZE = 64 * 1024 * 1024; | ||
| 635 | static const constexpr size_t RDB_MIN_MERGE_BUF_SIZE = 100; | ||
| 636 | static const constexpr size_t RDB_DEFAULT_MERGE_COMBINE_READ_SIZE = | ||
| 637 | 1024 * 1024 * 1024; | ||
| 638 | static const constexpr size_t RDB_MIN_MERGE_COMBINE_READ_SIZE = 100; | ||
| 639 | static const constexpr size_t RDB_DEFAULT_MERGE_TMP_FILE_REMOVAL_DELAY = 0; | ||
| 640 | static const constexpr size_t RDB_MIN_MERGE_TMP_FILE_REMOVAL_DELAY = 0; | ||
| 641 | static const constexpr int64 RDB_DEFAULT_BLOCK_CACHE_SIZE = 512 * 1024 * 1024; | ||
| 642 | static const constexpr int64 RDB_MIN_BLOCK_CACHE_SIZE = 1024; | ||
| 643 | static const constexpr int RDB_MAX_CHECKSUMS_PCT = 100; | ||
| 644 | static const constexpr uint32_t | ||
| 645 | RDB_DEFAULT_FORCE_COMPUTE_MEMTABLE_STATS_CACHETIME = 60 * 1000 * 1000; | ||
| 646 | static const constexpr ulong RDB_DEADLOCK_DETECT_DEPTH = 50; | ||
| 647 | static const constexpr uint ROCKSDB_MAX_BOTTOM_PRI_BACKGROUND_COMPACTIONS = 64; | ||
| 648 | static const constexpr uint64_t RDB_DEFAULT_MAX_COMPACTION_HISTORY = 64; | ||
| 649 | |||
| 650 | static long long rocksdb_block_cache_size = RDB_DEFAULT_BLOCK_CACHE_SIZE; | ||
| 651 | static long long rocksdb_sim_cache_size = 0; | ||
| 652 | static double rocksdb_cache_high_pri_pool_ratio = 0.0; | ||
| 653 | static bool rocksdb_cache_dump = false; | ||
| 654 | /* Use unsigned long long instead of uint64_t because of MySQL compatibility */ | ||
| 655 | static unsigned long long // NOLINT(runtime/int) | ||
| 656 | rocksdb_rate_limiter_bytes_per_sec = 0; | ||
| 657 | static unsigned long long // NOLINT(runtime/int) | ||
| 658 | rocksdb_sst_mgr_rate_bytes_per_sec = DEFAULT_SST_MGR_RATE_BYTES_PER_SEC; | ||
| 659 | static unsigned long long rocksdb_delayed_write_rate; | ||
| 660 | static uint32_t rocksdb_max_latest_deadlocks = RDB_DEADLOCK_DETECT_DEPTH; | ||
| 661 | static unsigned long // NOLINT(runtime/int) | ||
| 662 | rocksdb_persistent_cache_size_mb = 0; | ||
| 663 | static ulong rocksdb_info_log_level = rocksdb::InfoLogLevel::ERROR_LEVEL; | ||
| 664 | static char *rocksdb_wal_dir = nullptr; | ||
| 665 | static char *rocksdb_persistent_cache_path = nullptr; | ||
| 666 | static char *rocksdb_wsenv_path = nullptr; | ||
| 667 | static ulong rocksdb_index_type = | ||
| 668 | rocksdb::BlockBasedTableOptions::kBinarySearch; | ||
| 669 | static uint32_t rocksdb_flush_log_at_trx_commit = 1; | ||
| 670 | static uint32_t rocksdb_debug_optimizer_n_rows = 0; | ||
| 671 | static bool rocksdb_force_compute_memtable_stats = true; | ||
| 672 | static uint32_t rocksdb_force_compute_memtable_stats_cachetime = | ||
| 673 | RDB_DEFAULT_FORCE_COMPUTE_MEMTABLE_STATS_CACHETIME; | ||
| 674 | static bool rocksdb_debug_optimizer_no_zero_cardinality = true; | ||
| 675 | static uint32_t rocksdb_debug_cardinality_multiplier = 0; | ||
| 676 | static uint32_t rocksdb_wal_recovery_mode = | ||
| 677 | static_cast<uint32_t>(rocksdb::WALRecoveryMode::kPointInTimeRecovery); | ||
| 678 | static bool rocksdb_track_and_verify_wals_in_manifest = true; | ||
| 679 | static uint32_t rocksdb_stats_level = 0; | ||
| 680 | static uint32_t rocksdb_access_hint_on_compaction_start = | ||
| 681 | rocksdb::Options::AccessHint::NORMAL; | ||
| 682 | static char *rocksdb_compact_cf_name = nullptr; | ||
| 683 | static char *rocksdb_delete_cf_name = nullptr; | ||
| 684 | static char *rocksdb_checkpoint_name = nullptr; | ||
| 685 | static char *rocksdb_block_cache_trace_options_str = nullptr; | ||
| 686 | static char *rocksdb_trace_options_str = nullptr; | ||
| 687 | static bool rocksdb_signal_drop_index_thread = false; | ||
| 688 | static bool rocksdb_strict_collation_check = true; | ||
| 689 | static bool rocksdb_ignore_unknown_options = true; | ||
| 690 | static char *rocksdb_strict_collation_exceptions = nullptr; | ||
| 691 | static bool rocksdb_collect_sst_properties = true; | ||
| 692 | static bool rocksdb_force_flush_memtable_now_var = true; | ||
| 693 | static bool rocksdb_force_flush_memtable_and_lzero_now_var = false; | ||
| 694 | static bool rocksdb_cancel_manual_compactions_var = false; | ||
| 695 | static bool rocksdb_enable_ttl = true; | ||
| 696 | static bool rocksdb_enable_ttl_read_filtering = true; | ||
| 697 | static int rocksdb_debug_ttl_rec_ts = 0; | ||
| 698 | static int rocksdb_debug_ttl_snapshot_ts = 0; | ||
| 699 | static int rocksdb_debug_ttl_read_filter_ts = 0; | ||
| 700 | static bool rocksdb_debug_ttl_ignore_pk = false; | ||
| 701 | static bool rocksdb_reset_stats = false; | ||
| 702 | static uint32_t rocksdb_seconds_between_stat_computes = 3600; | ||
| 703 | static long long rocksdb_compaction_sequential_deletes = 0l; | ||
| 704 | static long long rocksdb_compaction_sequential_deletes_window = 0l; | ||
| 705 | static long long rocksdb_compaction_sequential_deletes_file_size = 0l; | ||
| 706 | #if defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 707 | static uint32_t rocksdb_validate_tables = 1; | ||
| 708 | #endif // defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && | ||
| 709 | // ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 710 | static char *rocksdb_datadir = nullptr; | ||
| 711 | static char *rocksdb_fs_uri; | ||
| 712 | static uint32_t rocksdb_max_bottom_pri_background_compactions = 0; | ||
| 713 | static uint32_t rocksdb_table_stats_sampling_pct = | ||
| 714 | RDB_DEFAULT_TBL_STATS_SAMPLE_PCT; | ||
| 715 | static uint32_t rocksdb_table_stats_recalc_threshold_pct = 10; | ||
| 716 | static unsigned long long rocksdb_table_stats_recalc_threshold_count = 100ul; | ||
| 717 | static bool rocksdb_table_stats_use_table_scan = 0; | ||
| 718 | static char *opt_rocksdb_fault_injection_options = nullptr; | ||
| 719 | static int32_t rocksdb_table_stats_background_thread_nice_value = | ||
| 720 | THREAD_PRIO_MAX; | ||
| 721 | static unsigned long long rocksdb_table_stats_max_num_rows_scanned = 0ul; | ||
| 722 | static bool rocksdb_enable_bulk_load_api = true; | ||
| 723 | static bool rocksdb_enable_remove_orphaned_dropped_cfs = true; | ||
| 724 | static bool rpl_skip_tx_api_var = false; | ||
| 725 | static bool rocksdb_print_snapshot_conflict_queries = false; | ||
| 726 | static bool rocksdb_large_prefix = true; | ||
| 727 | static bool rocksdb_allow_to_start_after_corruption = false; | ||
| 728 | static ulong rocksdb_write_policy = rocksdb::TxnDBWritePolicy::WRITE_COMMITTED; | ||
| 729 | char *rocksdb_read_free_rpl_tables; | ||
| 730 | ulong rocksdb_max_row_locks; | ||
| 731 | std::mutex rocksdb_read_free_rpl_tables_mutex; | ||
| 732 | #if defined(HAVE_PSI_INTERFACE) | ||
| 733 | Regex_list_handler rdb_read_free_regex_handler(key_rwlock_read_free_rpl_tables); | ||
| 734 | #else | ||
| 735 | Regex_list_handler rdb_read_free_regex_handler; | ||
| 736 | #endif | ||
| 737 | enum read_free_rpl_type { OFF = 0, PK_ONLY, PK_SK }; | ||
| 738 | static ulong rocksdb_read_free_rpl = read_free_rpl_type::OFF; | ||
| 739 | static bool rocksdb_error_on_suboptimal_collation = false; | ||
| 740 | static uint32_t rocksdb_stats_recalc_rate = 0; | ||
| 741 | static bool rocksdb_no_create_column_family = false; | ||
| 742 | static uint32_t rocksdb_debug_manual_compaction_delay = 0; | ||
| 743 | static uint32_t rocksdb_max_manual_compactions = 0; | ||
| 744 | static bool rocksdb_rollback_on_timeout = false; | ||
| 745 | static bool rocksdb_enable_insert_with_update_caching = true; | ||
| 746 | /* Use unsigned long long instead of uint64_t because of MySQL compatibility */ | ||
| 747 | static unsigned long long rocksdb_max_compaction_history = 0; | ||
| 748 | static bool rocksdb_skip_locks_if_skip_unique_check = false; | ||
| 749 | static bool rocksdb_alter_column_default_inplace = false; | ||
| 750 | static bool rocksdb_instant_ddl = false; | ||
| 751 | bool rocksdb_enable_tmp_table = false; | ||
| 752 | |||
| 753 | std::atomic<uint64_t> rocksdb_row_lock_deadlocks(0); | ||
| 754 | std::atomic<uint64_t> rocksdb_row_lock_wait_timeouts(0); | ||
| 755 | std::atomic<uint64_t> rocksdb_snapshot_conflict_errors(0); | ||
| 756 | std::atomic<uint64_t> rocksdb_wal_group_syncs(0); | ||
| 757 | std::atomic<uint64_t> rocksdb_manual_compactions_processed(0); | ||
| 758 | std::atomic<uint64_t> rocksdb_manual_compactions_cancelled(0); | ||
| 759 | std::atomic<uint64_t> rocksdb_manual_compactions_running(0); | ||
| 760 | std::atomic<uint64_t> rocksdb_manual_compactions_pending(0); | ||
| 761 | #ifndef NDEBUG | ||
| 762 | std::atomic<uint64_t> rocksdb_num_get_for_update_calls(0); | ||
| 763 | #endif | ||
| 764 | |||
| 765 | std::atomic<uint64_t> rocksdb_partial_index_groups_sorted(0); | ||
| 766 | std::atomic<uint64_t> rocksdb_partial_index_groups_materialized(0); | ||
| 767 | std::atomic<uint64_t> rocksdb_partial_index_rows_sorted(0); | ||
| 768 | std::atomic<uint64_t> rocksdb_partial_index_rows_materialized(0); | ||
| 769 | |||
| 770 | 15 | static int rocksdb_trace_block_cache_access( | |
| 771 | THD *const thd, struct SYS_VAR *const var, void *const save, | ||
| 772 | struct st_mysql_value *const value) { | ||
| 773 | 15 | return rocksdb_tracing(thd, var, save, value, | |
| 774 | 15 | /* trace_block_cache_accecss = */ true); | |
| 775 | } | ||
| 776 | |||
| 777 | 16 | static int rocksdb_trace_queries(THD *const thd, struct SYS_VAR *const var, | |
| 778 | void *const save, | ||
| 779 | struct st_mysql_value *const value) { | ||
| 780 | 16 | return rocksdb_tracing(thd, var, save, value, | |
| 781 | 16 | /* trace_block_cache_accecss = */ false); | |
| 782 | } | ||
| 783 | |||
| 784 | 31 | static int rocksdb_tracing(THD *const thd MY_ATTRIBUTE((__unused__)), | |
| 785 | struct SYS_VAR *const var, void *const save, | ||
| 786 | struct st_mysql_value *const value, | ||
| 787 | bool trace_block_cache_access) { | ||
| 788 | 31 | int len = 0; | |
| 789 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | const char *const trace_opt_str_raw = value->val_str(value, nullptr, &len); |
| 790 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
|
31 | if (trace_opt_str_raw == nullptr) { |
| 791 | 2 | return HA_EXIT_FAILURE; | |
| 792 | } | ||
| 793 | |||
| 794 | std::string trace_folder = | ||
| 795 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
|
29 | trace_block_cache_access ? "/block_cache_traces" : "/queries_traces"; |
| 796 | 29 | rocksdb::Status s; | |
| 797 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | if (rdb == nullptr) { |
| 798 | ✗ | return HA_EXIT_FAILURE; | |
| 799 | } | ||
| 800 | int rc __attribute__((__unused__)); | ||
| 801 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | std::string trace_opt_str(trace_opt_str_raw); |
| 802 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 23 times.
|
29 | if (trace_opt_str.empty()) { |
| 803 | // End tracing block cache accesses or queries. | ||
| 804 |
9/18✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
|
6 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 805 | "Stop tracing block cache accesses or queries.\n"); | ||
| 806 |
4/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | s = trace_block_cache_access ? rdb->EndBlockCacheTrace() : rdb->EndTrace(); |
| 807 | |||
| 808 |
3/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
|
6 | if (!s.ok()) { |
| 809 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | rc = ha_rocksdb::rdb_error_to_mysql(s); |
| 810 | 1 | return HA_EXIT_FAILURE; | |
| 811 | } | ||
| 812 | 5 | *static_cast<const char **>(save) = trace_opt_str_raw; | |
| 813 | 5 | return HA_EXIT_SUCCESS; | |
| 814 | } | ||
| 815 | |||
| 816 | // Start tracing block cache accesses or queries. | ||
| 817 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | std::stringstream ss(trace_opt_str); |
| 818 | 23 | std::vector<std::string> trace_opts_strs; | |
| 819 |
3/4✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 23 times.
|
88 | while (ss.good()) { |
| 820 | 65 | std::string substr; | |
| 821 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | getline(ss, substr, ':'); |
| 822 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | trace_opts_strs.push_back(substr); |
| 823 | 65 | } | |
| 824 | 23 | rocksdb::TraceOptions trace_opt; | |
| 825 | try { | ||
| 826 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 19 times.
|
23 | if (trace_opts_strs.size() != 3) { |
| 827 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | throw std::invalid_argument("Incorrect number of arguments."); |
| 828 | } | ||
| 829 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
|
19 | trace_opt.sampling_frequency = std::stoull(trace_opts_strs[0]); |
| 830 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | trace_opt.max_trace_file_size = std::stoull(trace_opts_strs[1]); |
| 831 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | } catch (const std::exception &e) { |
| 832 |
9/18✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 14 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
|
14 | LogPluginErrMsg( |
| 833 | INFORMATION_LEVEL, 0, | ||
| 834 | "Failed to parse trace option string: %s. The correct " | ||
| 835 | "format is sampling_frequency:max_trace_file_size:trace_file_name. " | ||
| 836 | "sampling_frequency and max_trace_file_size are positive integers. " | ||
| 837 | "The block accesses or quries are saved to the " | ||
| 838 | "rocksdb_datadir%s/trace_file_name.\n", | ||
| 839 | trace_opt_str.c_str(), trace_folder.c_str()); | ||
| 840 | 14 | return HA_EXIT_FAILURE; | |
| 841 | 14 | } | |
| 842 | 9 | const std::string &trace_file_name = trace_opts_strs[2]; | |
| 843 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (trace_file_name.find("/") != std::string::npos) { |
| 844 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 845 | "Start tracing failed (trace option string: %s). The file " | ||
| 846 | "name contains directory separator.\n", | ||
| 847 | trace_opt_str.c_str()); | ||
| 848 | ✗ | return HA_EXIT_FAILURE; | |
| 849 | } | ||
| 850 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
18 | const std::string trace_dir = std::string(rocksdb_datadir) + trace_folder; |
| 851 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | s = rdb->GetEnv()->CreateDirIfMissing(trace_dir); |
| 852 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if (!s.ok()) { |
| 853 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 854 | "Start tracing failed (trace option string: %s). Failed to " | ||
| 855 | "create the trace directory %s: %s\n", | ||
| 856 | trace_opt_str.c_str(), trace_dir.c_str(), | ||
| 857 | s.ToString().c_str()); | ||
| 858 | ✗ | return HA_EXIT_FAILURE; | |
| 859 | } | ||
| 860 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | const std::string trace_file_path = trace_dir + "/" + trace_file_name; |
| 861 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | s = rdb->GetEnv()->FileExists(trace_file_path); |
| 862 |
7/10✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 6 times.
|
9 | if (s.ok() || !s.IsNotFound()) { |
| 863 |
10/20✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
|
3 | LogPluginErrMsg( |
| 864 | INFORMATION_LEVEL, 0, | ||
| 865 | "Start tracing failed (trace option string: %s). The trace " | ||
| 866 | "file either already exists or we encountered an error " | ||
| 867 | "when calling rdb->GetEnv()->FileExists. The returned status string " | ||
| 868 | "is: %s\n", | ||
| 869 | trace_opt_str.c_str(), s.ToString().c_str()); | ||
| 870 | 3 | return HA_EXIT_FAILURE; | |
| 871 | } | ||
| 872 | 6 | std::unique_ptr<rocksdb::TraceWriter> trace_writer; | |
| 873 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | const rocksdb::EnvOptions env_option(rdb->GetDBOptions()); |
| 874 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | s = rocksdb::NewFileTraceWriter(rdb->GetEnv(), env_option, trace_file_path, |
| 875 | 6 | &trace_writer); | |
| 876 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (!s.ok()) { |
| 877 | ✗ | rc = ha_rocksdb::rdb_error_to_mysql(s); | |
| 878 | ✗ | return HA_EXIT_FAILURE; | |
| 879 | } | ||
| 880 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (trace_block_cache_access) { |
| 881 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | s = rdb->StartBlockCacheTrace(trace_opt, std::move(trace_writer)); |
| 882 | } else { | ||
| 883 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | s = rdb->StartTrace(trace_opt, std::move(trace_writer)); |
| 884 | } | ||
| 885 |
3/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
|
6 | if (!s.ok()) { |
| 886 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | rc = ha_rocksdb::rdb_error_to_mysql(s); |
| 887 | 1 | return HA_EXIT_FAILURE; | |
| 888 | } | ||
| 889 | // NO_LINT_DEBUG | ||
| 890 |
9/18✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
|
5 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 891 | "Start tracing block cache accesses or queries. Sampling " | ||
| 892 | "frequency: %" PRIu64 | ||
| 893 | ", " | ||
| 894 | "Maximum trace file size: %" PRIu64 ", Trace file path %s.\n", | ||
| 895 | trace_opt.sampling_frequency, trace_opt.max_trace_file_size, | ||
| 896 | trace_file_path.c_str()); | ||
| 897 | // Save the trace option. | ||
| 898 | 5 | *static_cast<const char **>(save) = trace_opt_str_raw; | |
| 899 | 5 | return HA_EXIT_SUCCESS; | |
| 900 | 29 | } | |
| 901 | |||
| 902 | 935 | static std::unique_ptr<rocksdb::DBOptions> rdb_init_rocksdb_db_options(void) { | |
| 903 |
1/2✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
|
935 | auto o = std::unique_ptr<rocksdb::DBOptions>(new rocksdb::DBOptions()); |
| 904 | |||
| 905 | 935 | o->create_if_missing = true; | |
| 906 |
2/4✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 935 times.
✗ Branch 3 not taken.
|
935 | o->listeners.push_back(std::make_shared<Rdb_event_listener>(&ddl_manager)); |
| 907 | 935 | o->info_log_level = rocksdb::InfoLogLevel::INFO_LEVEL; | |
| 908 | 935 | o->max_background_jobs = RDB_DEFAULT_MAX_BACKGROUND_JOBS; | |
| 909 | 935 | o->max_subcompactions = DEFAULT_SUBCOMPACTIONS; | |
| 910 | 935 | o->max_open_files = -2; // auto-tune to 50% open_files_limit | |
| 911 | 935 | o->max_total_wal_size = RDB_DEFAULT_MAX_TOTAL_WAL_SIZE; | |
| 912 | 935 | o->table_cache_numshardbits = RDB_DEFAULT_TABLE_CACHE_NUMSHARDBITS; | |
| 913 | |||
| 914 | 935 | o->two_write_queues = true; | |
| 915 | 935 | o->manual_wal_flush = true; | |
| 916 | 935 | return o; | |
| 917 | } | ||
| 918 | |||
| 919 | static std::unique_ptr<rocksdb::BlockBasedTableOptions> | ||
| 920 | 935 | rdb_init_rocksdb_tbl_options(void) { | |
| 921 | auto o = std::unique_ptr<rocksdb::BlockBasedTableOptions>( | ||
| 922 | 935 | new rocksdb::BlockBasedTableOptions()); | |
| 923 | 935 | o->block_size = RDB_DEFAULT_BLOCK_SIZE; | |
| 924 | 935 | return o; | |
| 925 | } | ||
| 926 | |||
| 927 | ✗ | static rocksdb::Env *GetCompositeEnv(std::shared_ptr<rocksdb::FileSystem> fs) { | |
| 928 | static std::shared_ptr<rocksdb::Env> composite_env = | ||
| 929 | ✗ | rocksdb::NewCompositeEnv(fs); | |
| 930 | ✗ | return composite_env.get(); | |
| 931 | } | ||
| 932 | |||
| 933 | /* DBOptions contains Statistics and needs to be destructed last */ | ||
| 934 | static std::unique_ptr<rocksdb::BlockBasedTableOptions> rocksdb_tbl_options = | ||
| 935 | rdb_init_rocksdb_tbl_options(); | ||
| 936 | static std::unique_ptr<rocksdb::DBOptions> rocksdb_db_options = | ||
| 937 | rdb_init_rocksdb_db_options(); | ||
| 938 | |||
| 939 | static std::shared_ptr<rocksdb::RateLimiter> rocksdb_rate_limiter; | ||
| 940 | |||
| 941 | /* This enum needs to be kept up to date with rocksdb::TxnDBWritePolicy */ | ||
| 942 | static const char *write_policy_names[] = {"write_committed", "write_prepared", | ||
| 943 | "write_unprepared", NullS}; | ||
| 944 | |||
| 945 | static TYPELIB write_policy_typelib = {array_elements(write_policy_names) - 1, | ||
| 946 | "write_policy_typelib", | ||
| 947 | write_policy_names, nullptr}; | ||
| 948 | |||
| 949 | /* This array needs to be kept up to date with myrocks::read_free_rpl_type */ | ||
| 950 | static const char *read_free_rpl_names[] = {"OFF", "PK_ONLY", "PK_SK", NullS}; | ||
| 951 | |||
| 952 | static TYPELIB read_free_rpl_typelib = {array_elements(read_free_rpl_names) - 1, | ||
| 953 | "read_free_rpl_typelib", | ||
| 954 | read_free_rpl_names, nullptr}; | ||
| 955 | |||
| 956 | /* This enum needs to be kept up to date with rocksdb::InfoLogLevel */ | ||
| 957 | static const char *info_log_level_names[] = {"debug_level", "info_level", | ||
| 958 | "warn_level", "error_level", | ||
| 959 | "fatal_level", NullS}; | ||
| 960 | |||
| 961 | static TYPELIB info_log_level_typelib = { | ||
| 962 | array_elements(info_log_level_names) - 1, "info_log_level_typelib", | ||
| 963 | info_log_level_names, nullptr}; | ||
| 964 | |||
| 965 | /* This enum needs to be kept up to date with rocksdb::BottommostLevelCompaction | ||
| 966 | */ | ||
| 967 | static const char *bottommost_level_compaction_names[] = { | ||
| 968 | "kSkip", "kIfHaveCompactionFilter", "kForce", "kForceOptimized", NullS}; | ||
| 969 | |||
| 970 | static TYPELIB bottommost_level_compaction_typelib = { | ||
| 971 | array_elements(bottommost_level_compaction_names) - 1, | ||
| 972 | "bottommost_level_compaction_typelib", bottommost_level_compaction_names, | ||
| 973 | nullptr}; | ||
| 974 | |||
| 975 | 11 | static void rocksdb_set_rocksdb_info_log_level( | |
| 976 | THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 977 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 978 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 979 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | assert(save != nullptr); |
| 980 | |||
| 981 | 11 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 982 | 11 | rocksdb_info_log_level = *static_cast<const uint64_t *>(save); | |
| 983 | 11 | rocksdb_db_options->info_log->SetInfoLogLevel( | |
| 984 | 11 | static_cast<rocksdb::InfoLogLevel>(rocksdb_info_log_level)); | |
| 985 | 11 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 986 | 11 | } | |
| 987 | |||
| 988 | 7 | static void rocksdb_set_rocksdb_stats_level(THD *const thd, | |
| 989 | struct SYS_VAR *const var, | ||
| 990 | void *const var_ptr, | ||
| 991 | const void *const save) { | ||
| 992 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(save != nullptr); |
| 993 | |||
| 994 | 7 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 995 | 7 | rocksdb_db_options->statistics->set_stats_level( | |
| 996 | 7 | static_cast<rocksdb::StatsLevel>(*static_cast<const uint64_t *>(save))); | |
| 997 | // Actual stats level is defined at rocksdb dbopt::statistics::stats_level_ | ||
| 998 | // so adjusting rocksdb_stats_level here to make sure it points to | ||
| 999 | // the correct stats level. | ||
| 1000 | 7 | rocksdb_stats_level = rocksdb_db_options->statistics->get_stats_level(); | |
| 1001 | 7 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 1002 | 7 | } | |
| 1003 | |||
| 1004 | 13 | static void rocksdb_set_reset_stats(my_core::THD *const /* unused */, | |
| 1005 | my_core::SYS_VAR *const /* unused */, | ||
| 1006 | void *const var_ptr, | ||
| 1007 | const void *const save) { | ||
| 1008 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(save != nullptr); |
| 1009 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(rdb != nullptr); |
| 1010 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(rocksdb_stats != nullptr); |
| 1011 | |||
| 1012 | 13 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 1013 | |||
| 1014 | 13 | *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 1015 | |||
| 1016 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
|
13 | if (rocksdb_reset_stats) { |
| 1017 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rocksdb::Status s = rdb->ResetStats(); |
| 1018 | |||
| 1019 | // RocksDB will always return success. Let's document this assumption here | ||
| 1020 | // as well so that we'll get immediately notified when contract changes. | ||
| 1021 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | assert(s == rocksdb::Status::OK()); |
| 1022 | |||
| 1023 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | s = rocksdb_stats->Reset(); |
| 1024 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | assert(s == rocksdb::Status::OK()); |
| 1025 | 3 | } | |
| 1026 | |||
| 1027 | 13 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 1028 | 13 | } | |
| 1029 | |||
| 1030 | enum rocksdb_flush_log_at_trx_commit_type : unsigned int { | ||
| 1031 | FLUSH_LOG_NEVER = 0, | ||
| 1032 | FLUSH_LOG_SYNC, | ||
| 1033 | FLUSH_LOG_BACKGROUND, | ||
| 1034 | FLUSH_LOG_MAX /* must be last */ | ||
| 1035 | }; | ||
| 1036 | |||
| 1037 | static int rocksdb_validate_flush_log_at_trx_commit( | ||
| 1038 | THD *const thd, | ||
| 1039 | struct SYS_VAR *const var, /* in: pointer to system variable */ | ||
| 1040 | void *var_ptr, /* out: immediate result for update function */ | ||
| 1041 | struct st_mysql_value *const value /* in: incoming value */); | ||
| 1042 | static int rocksdb_check_write_disable_wal( | ||
| 1043 | THD *const thd, struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 1044 | struct st_mysql_value *value); | ||
| 1045 | 1205 | static void rocksdb_compact_column_family_stub(THD *const thd, | |
| 1046 | struct SYS_VAR *const var, | ||
| 1047 | void *const var_ptr, | ||
| 1048 | 1205 | const void *const save) {} | |
| 1049 | |||
| 1050 | static int rocksdb_compact_column_family(THD *const thd, | ||
| 1051 | struct SYS_VAR *const var, | ||
| 1052 | void *const var_ptr, | ||
| 1053 | struct st_mysql_value *const value); | ||
| 1054 | |||
| 1055 | static const char *index_type_names[] = {"kBinarySearch", "kHashSearch", NullS}; | ||
| 1056 | |||
| 1057 | static TYPELIB index_type_typelib = {array_elements(index_type_names) - 1, | ||
| 1058 | "index_type_typelib", index_type_names, | ||
| 1059 | nullptr}; | ||
| 1060 | |||
| 1061 | // TODO: 0 means don't wait at all, and we don't support it yet? | ||
| 1062 | static MYSQL_THDVAR_ULONG(lock_wait_timeout, | ||
| 1063 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1064 | "Number of seconds to wait for lock", nullptr, | ||
| 1065 | nullptr, /*default*/ 1, /*min*/ 1, | ||
| 1066 | /*max*/ RDB_MAX_LOCK_WAIT_SECONDS, 0); | ||
| 1067 | |||
| 1068 | static MYSQL_THDVAR_BOOL(deadlock_detect, PLUGIN_VAR_RQCMDARG, | ||
| 1069 | "Enables deadlock detection", nullptr, nullptr, false); | ||
| 1070 | |||
| 1071 | static MYSQL_THDVAR_ULONG(deadlock_detect_depth, PLUGIN_VAR_RQCMDARG, | ||
| 1072 | "Number of transactions deadlock detection will " | ||
| 1073 | "traverse through before assuming deadlock", | ||
| 1074 | nullptr, nullptr, | ||
| 1075 | /*default*/ RDB_DEADLOCK_DETECT_DEPTH, | ||
| 1076 | /*min*/ 2, | ||
| 1077 | /*max*/ ULONG_MAX, 0); | ||
| 1078 | |||
| 1079 | static MYSQL_THDVAR_BOOL( | ||
| 1080 | commit_time_batch_for_recovery, PLUGIN_VAR_RQCMDARG, | ||
| 1081 | "TransactionOptions::commit_time_batch_for_recovery for RocksDB", nullptr, | ||
| 1082 | nullptr, false); | ||
| 1083 | |||
| 1084 | static MYSQL_THDVAR_BOOL( | ||
| 1085 | trace_sst_api, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1086 | "Generate trace output in the log for each call to the SstFileWriter", | ||
| 1087 | nullptr, nullptr, false); | ||
| 1088 | |||
| 1089 | static MYSQL_THDVAR_BOOL( | ||
| 1090 | bulk_load, PLUGIN_VAR_RQCMDARG, | ||
| 1091 | "Use bulk-load mode for inserts. This disables " | ||
| 1092 | "unique_checks and enables rocksdb_commit_in_the_middle.", | ||
| 1093 | rocksdb_check_bulk_load, nullptr, false); | ||
| 1094 | |||
| 1095 | static MYSQL_THDVAR_BOOL(bulk_load_allow_sk, PLUGIN_VAR_RQCMDARG, | ||
| 1096 | "Allow bulk loading of sk keys during bulk-load. " | ||
| 1097 | "Can be changed only when bulk load is disabled.", | ||
| 1098 | /* Intentionally reuse unsorted's check function */ | ||
| 1099 | rocksdb_check_bulk_load_allow_unsorted, nullptr, | ||
| 1100 | false); | ||
| 1101 | |||
| 1102 | static MYSQL_THDVAR_BOOL(bulk_load_allow_unsorted, PLUGIN_VAR_RQCMDARG, | ||
| 1103 | "Allow unsorted input during bulk-load. " | ||
| 1104 | "Can be changed only when bulk load is disabled.", | ||
| 1105 | rocksdb_check_bulk_load_allow_unsorted, nullptr, | ||
| 1106 | false); | ||
| 1107 | |||
| 1108 | static MYSQL_SYSVAR_BOOL(enable_bulk_load_api, rocksdb_enable_bulk_load_api, | ||
| 1109 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1110 | "Enables using SstFileWriter for bulk loading", | ||
| 1111 | nullptr, nullptr, rocksdb_enable_bulk_load_api); | ||
| 1112 | |||
| 1113 | static MYSQL_SYSVAR_BOOL( | ||
| 1114 | enable_pipelined_write, | ||
| 1115 | *reinterpret_cast<bool *>(&rocksdb_db_options->enable_pipelined_write), | ||
| 1116 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1117 | "DBOptions::enable_pipelined_write for RocksDB", nullptr, nullptr, | ||
| 1118 | rocksdb_db_options->enable_pipelined_write); | ||
| 1119 | |||
| 1120 | static MYSQL_SYSVAR_BOOL(enable_remove_orphaned_dropped_cfs, | ||
| 1121 | rocksdb_enable_remove_orphaned_dropped_cfs, | ||
| 1122 | PLUGIN_VAR_RQCMDARG, | ||
| 1123 | "Enables removing dropped cfs from metadata if it " | ||
| 1124 | "doesn't exist in cf manager", | ||
| 1125 | nullptr, nullptr, | ||
| 1126 | rocksdb_enable_remove_orphaned_dropped_cfs); | ||
| 1127 | |||
| 1128 | static MYSQL_THDVAR_STR(tmpdir, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 1129 | "Directory for temporary files during DDL operations.", | ||
| 1130 | nullptr, nullptr, ""); | ||
| 1131 | |||
| 1132 | static MYSQL_THDVAR_BOOL( | ||
| 1133 | commit_in_the_middle, PLUGIN_VAR_RQCMDARG, | ||
| 1134 | "Commit rows implicitly every rocksdb_bulk_load_size, on bulk load/insert, " | ||
| 1135 | "update and delete", | ||
| 1136 | nullptr, nullptr, false); | ||
| 1137 | |||
| 1138 | #if defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 1139 | |||
| 1140 | static MYSQL_THDVAR_BOOL( | ||
| 1141 | blind_delete_primary_key, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1142 | "Deleting rows by primary key lookup, without reading rows (Blind Deletes)." | ||
| 1143 | " Blind delete is disabled if the table has secondary key", | ||
| 1144 | nullptr, nullptr, false); | ||
| 1145 | |||
| 1146 | static MYSQL_THDVAR_BOOL( | ||
| 1147 | enable_iterate_bounds, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1148 | "Enable rocksdb iterator upper/lower bounds in read options.", nullptr, | ||
| 1149 | nullptr, true); | ||
| 1150 | |||
| 1151 | static const char *DEFAULT_READ_FREE_RPL_TABLES = ".*"; | ||
| 1152 | |||
| 1153 | 1882 | static std::regex_constants::syntax_option_type get_regex_flags() { | |
| 1154 | 1882 | std::regex_constants::syntax_option_type flags = | |
| 1155 | std::regex::nosubs | std::regex::extended; | ||
| 1156 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1854 times.
|
1882 | if (lower_case_table_names) { |
| 1157 | 28 | flags |= std::regex::icase; | |
| 1158 | } | ||
| 1159 | 1882 | return flags; | |
| 1160 | } | ||
| 1161 | |||
| 1162 | 5 | static int rocksdb_validate_read_free_rpl_tables( | |
| 1163 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 1164 | struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 1165 | struct st_mysql_value *value) { | ||
| 1166 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 1167 | 5 | int length = sizeof(buff); | |
| 1168 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | const char *wlist_buf = value->val_str(value, buff, &length); |
| 1169 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | if (wlist_buf) |
| 1170 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | wlist_buf = thd->strmake(wlist_buf, length); // make a temp copy |
| 1171 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | const auto wlist = wlist_buf ? wlist_buf : DEFAULT_READ_FREE_RPL_TABLES; |
| 1172 | |||
| 1173 | #if defined(HAVE_PSI_INTERFACE) | ||
| 1174 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | Regex_list_handler regex_handler(key_rwlock_read_free_rpl_tables); |
| 1175 | #else | ||
| 1176 | Regex_list_handler regex_handler; | ||
| 1177 | #endif | ||
| 1178 | |||
| 1179 |
4/6✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
|
5 | if (!regex_handler.set_patterns(wlist, get_regex_flags())) { |
| 1180 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | warn_about_bad_patterns(®ex_handler, "rocksdb_read_free_rpl_tables"); |
| 1181 | 1 | return HA_EXIT_FAILURE; | |
| 1182 | } | ||
| 1183 | |||
| 1184 | 4 | *static_cast<const char **>(save) = wlist; | |
| 1185 | 4 | return HA_EXIT_SUCCESS; | |
| 1186 | 5 | } | |
| 1187 | |||
| 1188 | 7 | static void rocksdb_update_read_free_rpl_tables( | |
| 1189 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 1190 | struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *var_ptr, | ||
| 1191 | const void *save) { | ||
| 1192 | 7 | const auto wlist = *static_cast<const char *const *>(save); | |
| 1193 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(wlist != nullptr); |
| 1194 | |||
| 1195 | // This is bound to succeed since we've already checked for bad patterns in | ||
| 1196 | // rocksdb_validate_read_free_rpl_tables | ||
| 1197 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | rdb_read_free_regex_handler.set_patterns(wlist, get_regex_flags()); |
| 1198 | |||
| 1199 | // update all table defs | ||
| 1200 | struct Rdb_read_free_rpl_updater : public Rdb_tables_scanner { | ||
| 1201 | ✗ | int add_table(Rdb_tbl_def *tdef) override { | |
| 1202 | ✗ | tdef->check_and_set_read_free_rpl_table(); | |
| 1203 | ✗ | return HA_EXIT_SUCCESS; | |
| 1204 | } | ||
| 1205 | 7 | } updater; | |
| 1206 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | ddl_manager.scan_for_tables(&updater); |
| 1207 | |||
| 1208 | 7 | *static_cast<const char **>(var_ptr) = *static_cast<char *const *>(save); | |
| 1209 | 7 | } | |
| 1210 | |||
| 1211 | 913 | static void rocksdb_set_max_bottom_pri_background_compactions_internal( | |
| 1212 | uint val) { | ||
| 1213 | // Set lower priority for compactions | ||
| 1214 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 896 times.
|
913 | if (val > 0) { |
| 1215 | // This creates background threads in rocksdb with BOTTOM priority pool. | ||
| 1216 | // Compactions for bottommost level use threads in the BOTTOM pool, and | ||
| 1217 | // the threads in the BOTTOM pool run with lower OS priority (19 in Linux). | ||
| 1218 | 17 | rdb->GetEnv()->SetBackgroundThreads(val, rocksdb::Env::Priority::BOTTOM); | |
| 1219 | 17 | rdb->GetEnv()->LowerThreadPoolCPUPriority(rocksdb::Env::Priority::BOTTOM); | |
| 1220 |
8/16✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 17 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 17 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 17 times.
✗ Branch 15 not taken.
|
17 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 1221 | "Set %d compaction thread(s) with " | ||
| 1222 | "lower scheduling priority.", | ||
| 1223 | val); | ||
| 1224 | } | ||
| 1225 | 913 | } | |
| 1226 | |||
| 1227 | static MYSQL_SYSVAR_STR( | ||
| 1228 | read_free_rpl_tables, rocksdb_read_free_rpl_tables, | ||
| 1229 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 1230 | "Regex that describes set of tables that will use read-free replication " | ||
| 1231 | "on the slave (i.e. not lookup a row during replication)", | ||
| 1232 | rocksdb_validate_read_free_rpl_tables, rocksdb_update_read_free_rpl_tables, | ||
| 1233 | DEFAULT_READ_FREE_RPL_TABLES); | ||
| 1234 | |||
| 1235 | static MYSQL_SYSVAR_ENUM( | ||
| 1236 | read_free_rpl, rocksdb_read_free_rpl, | ||
| 1237 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 1238 | "Use read-free replication on the slave (i.e. no row lookup during " | ||
| 1239 | "replication). Default is OFF, PK_SK will enable it on all tables with " | ||
| 1240 | "primary key. PK_ONLY will enable it on tables where the only key is the " | ||
| 1241 | "primary key (i.e. no secondary keys).", | ||
| 1242 | nullptr, nullptr, read_free_rpl_type::OFF, &read_free_rpl_typelib); | ||
| 1243 | #endif // defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 1244 | |||
| 1245 | static MYSQL_SYSVAR_BOOL( | ||
| 1246 | rpl_skip_tx_api, rpl_skip_tx_api_var, PLUGIN_VAR_RQCMDARG, | ||
| 1247 | "Use write batches for replication thread instead of tx api", nullptr, | ||
| 1248 | nullptr, false); | ||
| 1249 | |||
| 1250 | static MYSQL_THDVAR_BOOL(skip_bloom_filter_on_read, | ||
| 1251 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1252 | "Skip using bloom filter for reads", nullptr, nullptr, | ||
| 1253 | false); | ||
| 1254 | |||
| 1255 | static MYSQL_SYSVAR_ULONG(max_row_locks, rocksdb_max_row_locks, | ||
| 1256 | PLUGIN_VAR_RQCMDARG, | ||
| 1257 | "Maximum number of locks a transaction can have", | ||
| 1258 | nullptr, nullptr, | ||
| 1259 | /*default*/ RDB_DEFAULT_ROW_LOCKS, | ||
| 1260 | /*min*/ 1, | ||
| 1261 | /*max*/ RDB_MAX_ROW_LOCKS, 0); | ||
| 1262 | |||
| 1263 | static MYSQL_THDVAR_ULONGLONG( | ||
| 1264 | write_batch_max_bytes, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1265 | "Maximum size of write batch in bytes. 0 means no limit.", nullptr, nullptr, | ||
| 1266 | /* default */ 0, /* min */ 0, /* max */ SIZE_T_MAX, 1); | ||
| 1267 | |||
| 1268 | static MYSQL_THDVAR_ULONGLONG( | ||
| 1269 | write_batch_flush_threshold, | ||
| 1270 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1271 | "Maximum size of write batch in bytes before flushing. Only valid if " | ||
| 1272 | "rocksdb_write_policy is WRITE_UNPREPARED. 0 means no limit.", | ||
| 1273 | nullptr, nullptr, /* default */ 0, /* min */ 0, /* max */ SIZE_T_MAX, 1); | ||
| 1274 | |||
| 1275 | static MYSQL_THDVAR_BOOL( | ||
| 1276 | lock_scanned_rows, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1277 | "Take and hold locks on rows that are scanned but not updated", nullptr, | ||
| 1278 | nullptr, false); | ||
| 1279 | |||
| 1280 | static MYSQL_THDVAR_ULONG(bulk_load_size, | ||
| 1281 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1282 | "Max #records in a batch for bulk-load mode", nullptr, | ||
| 1283 | nullptr, | ||
| 1284 | /*default*/ RDB_DEFAULT_BULK_LOAD_SIZE, | ||
| 1285 | /*min*/ 1, | ||
| 1286 | /*max*/ RDB_MAX_BULK_LOAD_SIZE, 0); | ||
| 1287 | |||
| 1288 | static MYSQL_THDVAR_BOOL( | ||
| 1289 | bulk_load_partial_index, PLUGIN_VAR_RQCMDARG, | ||
| 1290 | "Materialize partial index during bulk load, instead of leaving it empty.", | ||
| 1291 | nullptr, nullptr, true); | ||
| 1292 | |||
| 1293 | static MYSQL_THDVAR_ULONGLONG( | ||
| 1294 | merge_buf_size, PLUGIN_VAR_RQCMDARG, | ||
| 1295 | "Size to allocate for merge sort buffers written out to disk " | ||
| 1296 | "during inplace index creation.", | ||
| 1297 | nullptr, nullptr, | ||
| 1298 | /* default (64MB) */ RDB_DEFAULT_MERGE_BUF_SIZE, | ||
| 1299 | /* min (100B) */ RDB_MIN_MERGE_BUF_SIZE, | ||
| 1300 | /* max */ SIZE_T_MAX, 1); | ||
| 1301 | |||
| 1302 | static MYSQL_THDVAR_ULONGLONG( | ||
| 1303 | merge_combine_read_size, PLUGIN_VAR_RQCMDARG, | ||
| 1304 | "Size that we have to work with during combine (reading from disk) phase " | ||
| 1305 | "of " | ||
| 1306 | "external sort during fast index creation.", | ||
| 1307 | nullptr, nullptr, | ||
| 1308 | /* default (1GB) */ RDB_DEFAULT_MERGE_COMBINE_READ_SIZE, | ||
| 1309 | /* min (100B) */ RDB_MIN_MERGE_COMBINE_READ_SIZE, | ||
| 1310 | /* max */ SIZE_T_MAX, 1); | ||
| 1311 | |||
| 1312 | static MYSQL_THDVAR_ULONGLONG( | ||
| 1313 | merge_tmp_file_removal_delay_ms, PLUGIN_VAR_RQCMDARG, | ||
| 1314 | "Fast index creation creates a large tmp file on disk during index " | ||
| 1315 | "creation. Removing this large file all at once when index creation is " | ||
| 1316 | "complete can cause trim stalls on Flash. This variable specifies a " | ||
| 1317 | "duration to sleep (in milliseconds) between calling chsize() to truncate " | ||
| 1318 | "the file in chunks. The chunk size is the same as merge_buf_size.", | ||
| 1319 | nullptr, nullptr, | ||
| 1320 | /* default (0ms) */ RDB_DEFAULT_MERGE_TMP_FILE_REMOVAL_DELAY, | ||
| 1321 | /* min (0ms) */ RDB_MIN_MERGE_TMP_FILE_REMOVAL_DELAY, | ||
| 1322 | /* max */ SIZE_T_MAX, 1); | ||
| 1323 | |||
| 1324 | static MYSQL_THDVAR_INT( | ||
| 1325 | manual_compaction_threads, PLUGIN_VAR_RQCMDARG, | ||
| 1326 | "How many rocksdb threads to run for manual compactions", nullptr, nullptr, | ||
| 1327 | /* default rocksdb.dboption max_subcompactions */ 0, | ||
| 1328 | /* min */ 0, /* max */ 128, 0); | ||
| 1329 | |||
| 1330 | static MYSQL_THDVAR_ENUM( | ||
| 1331 | manual_compaction_bottommost_level, PLUGIN_VAR_RQCMDARG, | ||
| 1332 | "Option for bottommost level compaction during manual " | ||
| 1333 | "compaction", | ||
| 1334 | nullptr, nullptr, | ||
| 1335 | /* default */ | ||
| 1336 | (ulong)rocksdb::BottommostLevelCompaction::kForceOptimized, | ||
| 1337 | &bottommost_level_compaction_typelib); | ||
| 1338 | |||
| 1339 | static MYSQL_SYSVAR_BOOL( | ||
| 1340 | create_if_missing, | ||
| 1341 | *static_cast<bool *>(&rocksdb_db_options->create_if_missing), | ||
| 1342 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1343 | "DBOptions::create_if_missing for RocksDB", nullptr, nullptr, | ||
| 1344 | rocksdb_db_options->create_if_missing); | ||
| 1345 | |||
| 1346 | ✗ | static void concurrent_prepare_update(THD *thd, SYS_VAR *var, void *var_ptr, | |
| 1347 | const void *save) { | ||
| 1348 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, HA_ERR_WRONG_COMMAND, | |
| 1349 | "Using rocksdb_concurrent_prepare is deprecated and the " | ||
| 1350 | "parameter may be removed in future releases."); | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | static MYSQL_SYSVAR_BOOL( | ||
| 1354 | concurrent_prepare, | ||
| 1355 | *static_cast<bool *>(&rocksdb_db_options->two_write_queues), | ||
| 1356 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1357 | "DEPRECATED, use rocksdb_two_write_queries instead.", nullptr, | ||
| 1358 | concurrent_prepare_update, rocksdb_db_options->two_write_queues); | ||
| 1359 | |||
| 1360 | static MYSQL_SYSVAR_BOOL( | ||
| 1361 | two_write_queues, | ||
| 1362 | *static_cast<bool *>(&rocksdb_db_options->two_write_queues), | ||
| 1363 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1364 | "DBOptions::two_write_queues for RocksDB", nullptr, nullptr, | ||
| 1365 | rocksdb_db_options->two_write_queues); | ||
| 1366 | |||
| 1367 | static MYSQL_SYSVAR_BOOL( | ||
| 1368 | manual_wal_flush, | ||
| 1369 | *static_cast<bool *>(&rocksdb_db_options->manual_wal_flush), | ||
| 1370 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1371 | "DBOptions::manual_wal_flush for RocksDB", nullptr, nullptr, | ||
| 1372 | rocksdb_db_options->manual_wal_flush); | ||
| 1373 | |||
| 1374 | static MYSQL_SYSVAR_ENUM(write_policy, rocksdb_write_policy, | ||
| 1375 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1376 | "DBOptions::write_policy for RocksDB", nullptr, | ||
| 1377 | nullptr, rocksdb::TxnDBWritePolicy::WRITE_COMMITTED, | ||
| 1378 | &write_policy_typelib); | ||
| 1379 | |||
| 1380 | static MYSQL_SYSVAR_BOOL( | ||
| 1381 | create_missing_column_families, | ||
| 1382 | *static_cast<bool *>(&rocksdb_db_options->create_missing_column_families), | ||
| 1383 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1384 | "DBOptions::create_missing_column_families for RocksDB", nullptr, nullptr, | ||
| 1385 | rocksdb_db_options->create_missing_column_families); | ||
| 1386 | |||
| 1387 | static MYSQL_SYSVAR_BOOL( | ||
| 1388 | error_if_exists, *static_cast<bool *>(&rocksdb_db_options->error_if_exists), | ||
| 1389 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1390 | "DBOptions::error_if_exists for RocksDB", nullptr, nullptr, | ||
| 1391 | rocksdb_db_options->error_if_exists); | ||
| 1392 | |||
| 1393 | static MYSQL_SYSVAR_BOOL( | ||
| 1394 | paranoid_checks, *static_cast<bool *>(&rocksdb_db_options->paranoid_checks), | ||
| 1395 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1396 | "DBOptions::paranoid_checks for RocksDB", nullptr, nullptr, | ||
| 1397 | rocksdb_db_options->paranoid_checks); | ||
| 1398 | |||
| 1399 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 1400 | rate_limiter_bytes_per_sec, rocksdb_rate_limiter_bytes_per_sec, | ||
| 1401 | PLUGIN_VAR_RQCMDARG, "DBOptions::rate_limiter bytes_per_sec for RocksDB", | ||
| 1402 | nullptr, rocksdb_set_rate_limiter_bytes_per_sec, /* default */ 0L, | ||
| 1403 | /* min */ 0L, /* max */ MAX_RATE_LIMITER_BYTES_PER_SEC, 0); | ||
| 1404 | |||
| 1405 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 1406 | sst_mgr_rate_bytes_per_sec, rocksdb_sst_mgr_rate_bytes_per_sec, | ||
| 1407 | PLUGIN_VAR_RQCMDARG, | ||
| 1408 | "DBOptions::sst_file_manager rate_bytes_per_sec for RocksDB", nullptr, | ||
| 1409 | rocksdb_set_sst_mgr_rate_bytes_per_sec, | ||
| 1410 | /* default */ DEFAULT_SST_MGR_RATE_BYTES_PER_SEC, | ||
| 1411 | /* min */ 0L, /* max */ UINT64_MAX, 0); | ||
| 1412 | |||
| 1413 | static MYSQL_SYSVAR_ULONGLONG(delayed_write_rate, rocksdb_delayed_write_rate, | ||
| 1414 | PLUGIN_VAR_RQCMDARG, | ||
| 1415 | "DBOptions::delayed_write_rate", nullptr, | ||
| 1416 | rocksdb_set_delayed_write_rate, | ||
| 1417 | rocksdb_db_options->delayed_write_rate, 0, | ||
| 1418 | UINT64_MAX, 0); | ||
| 1419 | |||
| 1420 | static MYSQL_SYSVAR_UINT(max_latest_deadlocks, rocksdb_max_latest_deadlocks, | ||
| 1421 | PLUGIN_VAR_RQCMDARG, | ||
| 1422 | "Maximum number of recent " | ||
| 1423 | "deadlocks to store", | ||
| 1424 | nullptr, rocksdb_set_max_latest_deadlocks, | ||
| 1425 | rocksdb::kInitialMaxDeadlocks, 0, UINT32_MAX, 0); | ||
| 1426 | |||
| 1427 | static MYSQL_SYSVAR_ENUM( | ||
| 1428 | info_log_level, rocksdb_info_log_level, PLUGIN_VAR_RQCMDARG, | ||
| 1429 | "Filter level for info logs to be written mysqld error log. " | ||
| 1430 | "Valid values include 'debug_level', 'info_level', 'warn_level'" | ||
| 1431 | "'error_level' and 'fatal_level'.", | ||
| 1432 | nullptr, rocksdb_set_rocksdb_info_log_level, | ||
| 1433 | rocksdb::InfoLogLevel::ERROR_LEVEL, &info_log_level_typelib); | ||
| 1434 | |||
| 1435 | static MYSQL_THDVAR_INT( | ||
| 1436 | perf_context_level, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1437 | "Perf Context Level for rocksdb internal timer stat collection", nullptr, | ||
| 1438 | nullptr, | ||
| 1439 | /* default */ rocksdb::PerfLevel::kUninitialized, | ||
| 1440 | /* min */ rocksdb::PerfLevel::kUninitialized, | ||
| 1441 | /* max */ rocksdb::PerfLevel::kOutOfBounds - 1, 0); | ||
| 1442 | |||
| 1443 | static MYSQL_SYSVAR_UINT( | ||
| 1444 | wal_recovery_mode, rocksdb_wal_recovery_mode, PLUGIN_VAR_RQCMDARG, | ||
| 1445 | "DBOptions::wal_recovery_mode for RocksDB. Default is kPointInTimeRecovery", | ||
| 1446 | nullptr, nullptr, | ||
| 1447 | /* default */ (uint)rocksdb::WALRecoveryMode::kPointInTimeRecovery, | ||
| 1448 | /* min */ (uint)rocksdb::WALRecoveryMode::kTolerateCorruptedTailRecords, | ||
| 1449 | /* max */ (uint)rocksdb::WALRecoveryMode::kSkipAnyCorruptedRecords, 0); | ||
| 1450 | |||
| 1451 | static MYSQL_SYSVAR_BOOL( | ||
| 1452 | track_and_verify_wals_in_manifest, | ||
| 1453 | *reinterpret_cast<bool *>(&rocksdb_track_and_verify_wals_in_manifest), | ||
| 1454 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1455 | "DBOptions::track_and_verify_wals_in_manifest for RocksDB", nullptr, | ||
| 1456 | nullptr, true); | ||
| 1457 | |||
| 1458 | static MYSQL_SYSVAR_UINT( | ||
| 1459 | stats_level, rocksdb_stats_level, PLUGIN_VAR_RQCMDARG, | ||
| 1460 | "Statistics Level for RocksDB. Default is 1 (kExceptHistogramOrTimers)", | ||
| 1461 | nullptr, rocksdb_set_rocksdb_stats_level, | ||
| 1462 | /* default */ (uint)rocksdb::StatsLevel::kExceptHistogramOrTimers, | ||
| 1463 | /* min */ (uint)rocksdb::StatsLevel::kExceptTickers, | ||
| 1464 | /* max */ (uint)rocksdb::StatsLevel::kAll, 0); | ||
| 1465 | |||
| 1466 | static MYSQL_SYSVAR_ULONG(compaction_readahead_size, | ||
| 1467 | rocksdb_db_options->compaction_readahead_size, | ||
| 1468 | PLUGIN_VAR_RQCMDARG, | ||
| 1469 | "DBOptions::compaction_readahead_size for RocksDB", | ||
| 1470 | nullptr, nullptr, | ||
| 1471 | rocksdb_db_options->compaction_readahead_size, | ||
| 1472 | /* min */ 0L, /* max */ ULONG_MAX, 0); | ||
| 1473 | |||
| 1474 | static MYSQL_SYSVAR_UINT( | ||
| 1475 | access_hint_on_compaction_start, rocksdb_access_hint_on_compaction_start, | ||
| 1476 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1477 | "DBOptions::access_hint_on_compaction_start for RocksDB", nullptr, nullptr, | ||
| 1478 | /* default */ (uint)rocksdb::Options::AccessHint::NORMAL, | ||
| 1479 | /* min */ (uint)rocksdb::Options::AccessHint::NONE, | ||
| 1480 | /* max */ (uint)rocksdb::Options::AccessHint::WILLNEED, 0); | ||
| 1481 | |||
| 1482 | static MYSQL_SYSVAR_BOOL( | ||
| 1483 | allow_concurrent_memtable_write, | ||
| 1484 | *static_cast<bool *>(&rocksdb_db_options->allow_concurrent_memtable_write), | ||
| 1485 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1486 | "DBOptions::allow_concurrent_memtable_write for RocksDB", nullptr, nullptr, | ||
| 1487 | false); | ||
| 1488 | |||
| 1489 | static MYSQL_SYSVAR_BOOL( | ||
| 1490 | enable_write_thread_adaptive_yield, | ||
| 1491 | *static_cast<bool *>( | ||
| 1492 | &rocksdb_db_options->enable_write_thread_adaptive_yield), | ||
| 1493 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1494 | "DBOptions::enable_write_thread_adaptive_yield for RocksDB", nullptr, | ||
| 1495 | nullptr, false); | ||
| 1496 | |||
| 1497 | static MYSQL_SYSVAR_INT(max_open_files, rocksdb_db_options->max_open_files, | ||
| 1498 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1499 | "DBOptions::max_open_files for RocksDB", nullptr, | ||
| 1500 | nullptr, rocksdb_db_options->max_open_files, | ||
| 1501 | /* min */ -2, /* max */ INT_MAX, 0); | ||
| 1502 | |||
| 1503 | static MYSQL_SYSVAR_UINT64_T(max_total_wal_size, | ||
| 1504 | rocksdb_db_options->max_total_wal_size, | ||
| 1505 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1506 | "DBOptions::max_total_wal_size for RocksDB", | ||
| 1507 | nullptr, nullptr, | ||
| 1508 | rocksdb_db_options->max_total_wal_size, | ||
| 1509 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1510 | |||
| 1511 | static MYSQL_SYSVAR_BOOL(use_fsync, | ||
| 1512 | *static_cast<bool *>(&rocksdb_db_options->use_fsync), | ||
| 1513 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1514 | "DBOptions::use_fsync for RocksDB", nullptr, nullptr, | ||
| 1515 | rocksdb_db_options->use_fsync); | ||
| 1516 | |||
| 1517 | static MYSQL_SYSVAR_STR(wal_dir, rocksdb_wal_dir, | ||
| 1518 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1519 | "DBOptions::wal_dir for RocksDB", nullptr, nullptr, | ||
| 1520 | rocksdb_db_options->wal_dir.c_str()); | ||
| 1521 | |||
| 1522 | static MYSQL_SYSVAR_STR( | ||
| 1523 | persistent_cache_path, rocksdb_persistent_cache_path, | ||
| 1524 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1525 | "Path for BlockBasedTableOptions::persistent_cache for RocksDB", nullptr, | ||
| 1526 | nullptr, ""); | ||
| 1527 | |||
| 1528 | static MYSQL_SYSVAR_ULONG( | ||
| 1529 | persistent_cache_size_mb, rocksdb_persistent_cache_size_mb, | ||
| 1530 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1531 | "Size of cache in MB for BlockBasedTableOptions::persistent_cache " | ||
| 1532 | "for RocksDB", | ||
| 1533 | nullptr, nullptr, rocksdb_persistent_cache_size_mb, | ||
| 1534 | /* min */ 0L, /* max */ ULONG_MAX, 0); | ||
| 1535 | |||
| 1536 | static MYSQL_SYSVAR_STR(wsenv_path, rocksdb_wsenv_path, | ||
| 1537 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1538 | "Path for RocksDB WSEnv", nullptr, nullptr, ""); | ||
| 1539 | |||
| 1540 | static MYSQL_SYSVAR_STR(fault_injection_options, | ||
| 1541 | opt_rocksdb_fault_injection_options, | ||
| 1542 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1543 | "Fault injection options for running rocksdb tests", | ||
| 1544 | nullptr, nullptr, nullptr); | ||
| 1545 | |||
| 1546 | static MYSQL_SYSVAR_UINT64_T( | ||
| 1547 | delete_obsolete_files_period_micros, | ||
| 1548 | rocksdb_db_options->delete_obsolete_files_period_micros, | ||
| 1549 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1550 | "DBOptions::delete_obsolete_files_period_micros for RocksDB", nullptr, | ||
| 1551 | nullptr, rocksdb_db_options->delete_obsolete_files_period_micros, | ||
| 1552 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1553 | |||
| 1554 | static MYSQL_SYSVAR_INT(max_background_jobs, | ||
| 1555 | rocksdb_db_options->max_background_jobs, | ||
| 1556 | PLUGIN_VAR_RQCMDARG, | ||
| 1557 | "DBOptions::max_background_jobs for RocksDB", nullptr, | ||
| 1558 | rocksdb_set_max_background_jobs, | ||
| 1559 | rocksdb_db_options->max_background_jobs, | ||
| 1560 | /* min */ -1, /* max */ MAX_BACKGROUND_JOBS, 0); | ||
| 1561 | |||
| 1562 | static MYSQL_SYSVAR_INT(max_background_flushes, | ||
| 1563 | rocksdb_db_options->max_background_flushes, | ||
| 1564 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1565 | "DBOptions::max_background_flushes for RocksDB", | ||
| 1566 | nullptr, nullptr, | ||
| 1567 | rocksdb_db_options->max_background_flushes, | ||
| 1568 | /* min */ -1, /* max */ 64, 0); | ||
| 1569 | |||
| 1570 | static MYSQL_SYSVAR_INT(max_background_compactions, | ||
| 1571 | rocksdb_db_options->max_background_compactions, | ||
| 1572 | PLUGIN_VAR_RQCMDARG, | ||
| 1573 | "DBOptions::max_background_compactions for RocksDB", | ||
| 1574 | nullptr, rocksdb_set_max_background_compactions, | ||
| 1575 | rocksdb_db_options->max_background_compactions, | ||
| 1576 | /* min */ -1, /* max */ 64, 0); | ||
| 1577 | |||
| 1578 | static MYSQL_SYSVAR_UINT( | ||
| 1579 | max_bottom_pri_background_compactions, | ||
| 1580 | rocksdb_max_bottom_pri_background_compactions, PLUGIN_VAR_RQCMDARG, | ||
| 1581 | "Creating specified number of threads, setting lower " | ||
| 1582 | "CPU priority, and letting Lmax compactions use them. " | ||
| 1583 | "Maximum total compaction concurrency continues to be capped to " | ||
| 1584 | "rocksdb_max_background_compactions or " | ||
| 1585 | "rocksdb_max_background_jobs. In addition to that, Lmax " | ||
| 1586 | "compaction concurrency is capped to " | ||
| 1587 | "rocksdb_max_bottom_pri_background_compactions. Default value is 0, " | ||
| 1588 | "which means all compactions are under concurrency of " | ||
| 1589 | "rocksdb_max_background_compactions|jobs. If you set very low " | ||
| 1590 | "rocksdb_max_bottom_pri_background_compactions (e.g. 1 or 2), compactions " | ||
| 1591 | "may not be able to keep up. Since Lmax normally has " | ||
| 1592 | "90 percent of data, it is recommended to set closer number to " | ||
| 1593 | "rocksdb_max_background_compactions|jobs. This option is helpful to " | ||
| 1594 | "give more CPU resources to other threads (e.g. query processing).", | ||
| 1595 | rocksdb_validate_max_bottom_pri_background_compactions, nullptr, 0, | ||
| 1596 | /* min */ 0, /* max */ ROCKSDB_MAX_BOTTOM_PRI_BACKGROUND_COMPACTIONS, 0); | ||
| 1597 | |||
| 1598 | static MYSQL_SYSVAR_UINT(max_subcompactions, | ||
| 1599 | rocksdb_db_options->max_subcompactions, | ||
| 1600 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1601 | "DBOptions::max_subcompactions for RocksDB", nullptr, | ||
| 1602 | nullptr, rocksdb_db_options->max_subcompactions, | ||
| 1603 | /* min */ 1, /* max */ MAX_SUBCOMPACTIONS, 0); | ||
| 1604 | |||
| 1605 | static MYSQL_SYSVAR_ULONG(max_log_file_size, | ||
| 1606 | rocksdb_db_options->max_log_file_size, | ||
| 1607 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1608 | "DBOptions::max_log_file_size for RocksDB", nullptr, | ||
| 1609 | nullptr, rocksdb_db_options->max_log_file_size, | ||
| 1610 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1611 | |||
| 1612 | static MYSQL_SYSVAR_ULONG(log_file_time_to_roll, | ||
| 1613 | rocksdb_db_options->log_file_time_to_roll, | ||
| 1614 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1615 | "DBOptions::log_file_time_to_roll for RocksDB", | ||
| 1616 | nullptr, nullptr, | ||
| 1617 | rocksdb_db_options->log_file_time_to_roll, | ||
| 1618 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1619 | |||
| 1620 | static MYSQL_SYSVAR_ULONG(keep_log_file_num, | ||
| 1621 | rocksdb_db_options->keep_log_file_num, | ||
| 1622 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1623 | "DBOptions::keep_log_file_num for RocksDB", nullptr, | ||
| 1624 | nullptr, rocksdb_db_options->keep_log_file_num, | ||
| 1625 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1626 | |||
| 1627 | static MYSQL_SYSVAR_UINT64_T(max_manifest_file_size, | ||
| 1628 | rocksdb_db_options->max_manifest_file_size, | ||
| 1629 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1630 | "DBOptions::max_manifest_file_size for RocksDB", | ||
| 1631 | nullptr, nullptr, | ||
| 1632 | rocksdb_db_options->max_manifest_file_size, | ||
| 1633 | /* min */ 0L, /* max */ ULONG_MAX, 0); | ||
| 1634 | |||
| 1635 | static MYSQL_SYSVAR_INT(table_cache_numshardbits, | ||
| 1636 | rocksdb_db_options->table_cache_numshardbits, | ||
| 1637 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1638 | "DBOptions::table_cache_numshardbits for RocksDB", | ||
| 1639 | nullptr, nullptr, | ||
| 1640 | rocksdb_db_options->table_cache_numshardbits, | ||
| 1641 | /* min */ 0, /* max */ 19, 0); | ||
| 1642 | |||
| 1643 | static MYSQL_SYSVAR_UINT64_T(wal_ttl_seconds, | ||
| 1644 | rocksdb_db_options->WAL_ttl_seconds, | ||
| 1645 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1646 | "DBOptions::WAL_ttl_seconds for RocksDB", nullptr, | ||
| 1647 | nullptr, rocksdb_db_options->WAL_ttl_seconds, | ||
| 1648 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1649 | |||
| 1650 | static MYSQL_SYSVAR_UINT64_T(wal_size_limit_mb, | ||
| 1651 | rocksdb_db_options->WAL_size_limit_MB, | ||
| 1652 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1653 | "DBOptions::WAL_size_limit_MB for RocksDB", | ||
| 1654 | nullptr, nullptr, | ||
| 1655 | rocksdb_db_options->WAL_size_limit_MB, | ||
| 1656 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1657 | |||
| 1658 | static MYSQL_SYSVAR_ULONG(manifest_preallocation_size, | ||
| 1659 | rocksdb_db_options->manifest_preallocation_size, | ||
| 1660 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1661 | "DBOptions::manifest_preallocation_size for RocksDB", | ||
| 1662 | nullptr, nullptr, | ||
| 1663 | rocksdb_db_options->manifest_preallocation_size, | ||
| 1664 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1665 | |||
| 1666 | static MYSQL_SYSVAR_BOOL( | ||
| 1667 | use_direct_reads, | ||
| 1668 | *static_cast<bool *>(&rocksdb_db_options->use_direct_reads), | ||
| 1669 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1670 | "DBOptions::use_direct_reads for RocksDB", nullptr, nullptr, | ||
| 1671 | rocksdb_db_options->use_direct_reads); | ||
| 1672 | |||
| 1673 | static MYSQL_SYSVAR_BOOL( | ||
| 1674 | use_direct_io_for_flush_and_compaction, | ||
| 1675 | *static_cast<bool *>( | ||
| 1676 | &rocksdb_db_options->use_direct_io_for_flush_and_compaction), | ||
| 1677 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1678 | "DBOptions::use_direct_io_for_flush_and_compaction for RocksDB", nullptr, | ||
| 1679 | nullptr, rocksdb_db_options->use_direct_io_for_flush_and_compaction); | ||
| 1680 | |||
| 1681 | static MYSQL_SYSVAR_BOOL( | ||
| 1682 | allow_mmap_reads, | ||
| 1683 | *static_cast<bool *>(&rocksdb_db_options->allow_mmap_reads), | ||
| 1684 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1685 | "DBOptions::allow_mmap_reads for RocksDB", nullptr, nullptr, | ||
| 1686 | rocksdb_db_options->allow_mmap_reads); | ||
| 1687 | |||
| 1688 | static MYSQL_SYSVAR_BOOL( | ||
| 1689 | allow_mmap_writes, | ||
| 1690 | *static_cast<bool *>(&rocksdb_db_options->allow_mmap_writes), | ||
| 1691 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1692 | "DBOptions::allow_mmap_writes for RocksDB", nullptr, nullptr, | ||
| 1693 | rocksdb_db_options->allow_mmap_writes); | ||
| 1694 | |||
| 1695 | static MYSQL_SYSVAR_BOOL( | ||
| 1696 | is_fd_close_on_exec, | ||
| 1697 | *static_cast<bool *>(&rocksdb_db_options->is_fd_close_on_exec), | ||
| 1698 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1699 | "DBOptions::is_fd_close_on_exec for RocksDB", nullptr, nullptr, | ||
| 1700 | rocksdb_db_options->is_fd_close_on_exec); | ||
| 1701 | |||
| 1702 | static MYSQL_SYSVAR_UINT(stats_dump_period_sec, | ||
| 1703 | rocksdb_db_options->stats_dump_period_sec, | ||
| 1704 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1705 | "DBOptions::stats_dump_period_sec for RocksDB", | ||
| 1706 | nullptr, nullptr, | ||
| 1707 | rocksdb_db_options->stats_dump_period_sec, | ||
| 1708 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1709 | |||
| 1710 | static MYSQL_SYSVAR_BOOL( | ||
| 1711 | advise_random_on_open, | ||
| 1712 | *static_cast<bool *>(&rocksdb_db_options->advise_random_on_open), | ||
| 1713 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1714 | "DBOptions::advise_random_on_open for RocksDB", nullptr, nullptr, | ||
| 1715 | rocksdb_db_options->advise_random_on_open); | ||
| 1716 | |||
| 1717 | static MYSQL_SYSVAR_ULONG(db_write_buffer_size, | ||
| 1718 | rocksdb_db_options->db_write_buffer_size, | ||
| 1719 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1720 | "DBOptions::db_write_buffer_size for RocksDB", | ||
| 1721 | nullptr, nullptr, | ||
| 1722 | rocksdb_db_options->db_write_buffer_size, | ||
| 1723 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1724 | |||
| 1725 | static MYSQL_SYSVAR_BOOL( | ||
| 1726 | use_adaptive_mutex, | ||
| 1727 | *static_cast<bool *>(&rocksdb_db_options->use_adaptive_mutex), | ||
| 1728 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1729 | "DBOptions::use_adaptive_mutex for RocksDB", nullptr, nullptr, | ||
| 1730 | rocksdb_db_options->use_adaptive_mutex); | ||
| 1731 | |||
| 1732 | static MYSQL_SYSVAR_UINT64_T(bytes_per_sync, rocksdb_db_options->bytes_per_sync, | ||
| 1733 | PLUGIN_VAR_RQCMDARG, | ||
| 1734 | "DBOptions::bytes_per_sync for RocksDB", nullptr, | ||
| 1735 | rocksdb_set_bytes_per_sync, | ||
| 1736 | rocksdb_db_options->bytes_per_sync, | ||
| 1737 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1738 | |||
| 1739 | static MYSQL_SYSVAR_UINT64_T(wal_bytes_per_sync, | ||
| 1740 | rocksdb_db_options->wal_bytes_per_sync, | ||
| 1741 | PLUGIN_VAR_RQCMDARG, | ||
| 1742 | "DBOptions::wal_bytes_per_sync for RocksDB", | ||
| 1743 | nullptr, rocksdb_set_wal_bytes_per_sync, | ||
| 1744 | rocksdb_db_options->wal_bytes_per_sync, | ||
| 1745 | /* min */ 0L, /* max */ LONG_MAX, 0); | ||
| 1746 | |||
| 1747 | static MYSQL_SYSVAR_BOOL( | ||
| 1748 | enable_thread_tracking, | ||
| 1749 | *static_cast<bool *>(&rocksdb_db_options->enable_thread_tracking), | ||
| 1750 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1751 | "DBOptions::enable_thread_tracking for RocksDB", nullptr, nullptr, true); | ||
| 1752 | |||
| 1753 | static MYSQL_SYSVAR_LONGLONG(block_cache_size, rocksdb_block_cache_size, | ||
| 1754 | PLUGIN_VAR_RQCMDARG, | ||
| 1755 | "block_cache size for RocksDB", | ||
| 1756 | rocksdb_validate_set_block_cache_size, nullptr, | ||
| 1757 | /* default */ RDB_DEFAULT_BLOCK_CACHE_SIZE, | ||
| 1758 | /* min */ RDB_MIN_BLOCK_CACHE_SIZE, | ||
| 1759 | /* max */ LLONG_MAX, | ||
| 1760 | /* Block size */ RDB_MIN_BLOCK_CACHE_SIZE); | ||
| 1761 | |||
| 1762 | static MYSQL_SYSVAR_LONGLONG(sim_cache_size, rocksdb_sim_cache_size, | ||
| 1763 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1764 | "Simulated cache size for RocksDB", nullptr, | ||
| 1765 | nullptr, | ||
| 1766 | /* default */ 0, | ||
| 1767 | /* min */ 0, | ||
| 1768 | /* max */ LLONG_MAX, | ||
| 1769 | /* Block size */ 0); | ||
| 1770 | |||
| 1771 | static MYSQL_SYSVAR_BOOL(cache_dump, rocksdb_cache_dump, | ||
| 1772 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1773 | "Include RocksDB block cache content in core dump.", | ||
| 1774 | nullptr, nullptr, true); | ||
| 1775 | |||
| 1776 | static MYSQL_SYSVAR_DOUBLE(cache_high_pri_pool_ratio, | ||
| 1777 | rocksdb_cache_high_pri_pool_ratio, | ||
| 1778 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1779 | "Specify the size of block cache high-pri pool", | ||
| 1780 | nullptr, nullptr, /* default */ 0.0, /* min */ 0.0, | ||
| 1781 | /* max */ 1.0, 0); | ||
| 1782 | |||
| 1783 | static MYSQL_SYSVAR_BOOL( | ||
| 1784 | cache_index_and_filter_blocks, | ||
| 1785 | *static_cast<bool *>(&rocksdb_tbl_options->cache_index_and_filter_blocks), | ||
| 1786 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1787 | "BlockBasedTableOptions::cache_index_and_filter_blocks for RocksDB", | ||
| 1788 | nullptr, nullptr, true); | ||
| 1789 | |||
| 1790 | static MYSQL_SYSVAR_BOOL( | ||
| 1791 | cache_index_and_filter_with_high_priority, | ||
| 1792 | *reinterpret_cast<bool *>( | ||
| 1793 | &rocksdb_tbl_options->cache_index_and_filter_blocks_with_high_priority), | ||
| 1794 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1795 | "cache_index_and_filter_blocks_with_high_priority for RocksDB", nullptr, | ||
| 1796 | nullptr, true); | ||
| 1797 | |||
| 1798 | // When pin_l0_filter_and_index_blocks_in_cache is true, RocksDB will use the | ||
| 1799 | // LRU cache, but will always keep the filter & idndex block's handle checked | ||
| 1800 | // out (=won't call ShardedLRUCache::Release), plus the parsed out objects | ||
| 1801 | // the LRU cache will never push flush them out, hence they're pinned. | ||
| 1802 | // | ||
| 1803 | // This fixes the mutex contention between :ShardedLRUCache::Lookup and | ||
| 1804 | // ShardedLRUCache::Release which reduced the QPS ratio (QPS using secondary | ||
| 1805 | // index / QPS using PK). | ||
| 1806 | static MYSQL_SYSVAR_BOOL( | ||
| 1807 | pin_l0_filter_and_index_blocks_in_cache, | ||
| 1808 | *static_cast<bool *>( | ||
| 1809 | &rocksdb_tbl_options->pin_l0_filter_and_index_blocks_in_cache), | ||
| 1810 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1811 | "pin_l0_filter_and_index_blocks_in_cache for RocksDB", nullptr, nullptr, | ||
| 1812 | true); | ||
| 1813 | |||
| 1814 | static MYSQL_SYSVAR_ENUM(index_type, rocksdb_index_type, | ||
| 1815 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1816 | "BlockBasedTableOptions::index_type for RocksDB", | ||
| 1817 | nullptr, nullptr, | ||
| 1818 | (uint64_t)rocksdb_tbl_options->index_type, | ||
| 1819 | &index_type_typelib); | ||
| 1820 | |||
| 1821 | static MYSQL_SYSVAR_BOOL( | ||
| 1822 | no_block_cache, *static_cast<bool *>(&rocksdb_tbl_options->no_block_cache), | ||
| 1823 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1824 | "BlockBasedTableOptions::no_block_cache for RocksDB", nullptr, nullptr, | ||
| 1825 | rocksdb_tbl_options->no_block_cache); | ||
| 1826 | |||
| 1827 | static MYSQL_SYSVAR_UINT64_T(block_size, rocksdb_tbl_options->block_size, | ||
| 1828 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1829 | "BlockBasedTableOptions::block_size for RocksDB", | ||
| 1830 | nullptr, nullptr, rocksdb_tbl_options->block_size, | ||
| 1831 | /* min */ 1024L, /* max */ LONG_MAX, 0); | ||
| 1832 | |||
| 1833 | static MYSQL_SYSVAR_INT( | ||
| 1834 | block_size_deviation, rocksdb_tbl_options->block_size_deviation, | ||
| 1835 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1836 | "BlockBasedTableOptions::block_size_deviation for RocksDB", nullptr, | ||
| 1837 | nullptr, rocksdb_tbl_options->block_size_deviation, | ||
| 1838 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1839 | |||
| 1840 | static MYSQL_SYSVAR_INT( | ||
| 1841 | block_restart_interval, rocksdb_tbl_options->block_restart_interval, | ||
| 1842 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1843 | "BlockBasedTableOptions::block_restart_interval for RocksDB", nullptr, | ||
| 1844 | nullptr, rocksdb_tbl_options->block_restart_interval, | ||
| 1845 | /* min */ 1, /* max */ INT_MAX, 0); | ||
| 1846 | |||
| 1847 | static MYSQL_SYSVAR_BOOL( | ||
| 1848 | whole_key_filtering, | ||
| 1849 | *static_cast<bool *>(&rocksdb_tbl_options->whole_key_filtering), | ||
| 1850 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1851 | "BlockBasedTableOptions::whole_key_filtering for RocksDB", nullptr, nullptr, | ||
| 1852 | rocksdb_tbl_options->whole_key_filtering); | ||
| 1853 | |||
| 1854 | static MYSQL_SYSVAR_STR(default_cf_options, rocksdb_default_cf_options, | ||
| 1855 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1856 | "default cf options for RocksDB", nullptr, nullptr, | ||
| 1857 | "block_based_table_factory={cache_index_and_filter_" | ||
| 1858 | "blocks=1;filter_policy=bloomfilter:10:false;whole_key_" | ||
| 1859 | "filtering=1};level_compaction_dynamic_level_bytes=" | ||
| 1860 | "true;optimize_filters_for_hits=true;compaction_pri=" | ||
| 1861 | "kMinOverlappingRatio;compression=kLZ4Compression;" | ||
| 1862 | "bottommost_compression=kLZ4Compression;"); | ||
| 1863 | |||
| 1864 | static MYSQL_SYSVAR_STR(override_cf_options, rocksdb_override_cf_options, | ||
| 1865 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1866 | "option overrides per cf for RocksDB", nullptr, nullptr, | ||
| 1867 | ""); | ||
| 1868 | |||
| 1869 | static MYSQL_SYSVAR_STR(update_cf_options, rocksdb_update_cf_options, | ||
| 1870 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC | | ||
| 1871 | PLUGIN_VAR_NOCMDOPT, | ||
| 1872 | "Option updates per column family for RocksDB", | ||
| 1873 | rocksdb_validate_update_cf_options, | ||
| 1874 | rocksdb_set_update_cf_options, nullptr); | ||
| 1875 | |||
| 1876 | static MYSQL_SYSVAR_BOOL(use_default_sk_cf, rocksdb_use_default_sk_cf, | ||
| 1877 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1878 | "Use default_sk for secondary keys", nullptr, nullptr, | ||
| 1879 | false); | ||
| 1880 | |||
| 1881 | static MYSQL_SYSVAR_BOOL(allow_unsafe_alter, rocksdb_allow_unsafe_alter, | ||
| 1882 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 1883 | "Enable crash unsafe INPLACE ADD|DROP partition.", | ||
| 1884 | nullptr, nullptr, false); | ||
| 1885 | |||
| 1886 | static MYSQL_SYSVAR_UINT(flush_log_at_trx_commit, | ||
| 1887 | rocksdb_flush_log_at_trx_commit, PLUGIN_VAR_RQCMDARG, | ||
| 1888 | "Sync on transaction commit. Similar to " | ||
| 1889 | "innodb_flush_log_at_trx_commit. 1: sync on commit, " | ||
| 1890 | "0,2: not sync on commit", | ||
| 1891 | rocksdb_validate_flush_log_at_trx_commit, nullptr, | ||
| 1892 | /* default */ FLUSH_LOG_SYNC, | ||
| 1893 | /* min */ FLUSH_LOG_NEVER, | ||
| 1894 | /* max */ FLUSH_LOG_BACKGROUND, 0); | ||
| 1895 | |||
| 1896 | static MYSQL_THDVAR_BOOL(write_disable_wal, | ||
| 1897 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1898 | "WriteOptions::disableWAL for RocksDB", | ||
| 1899 | rocksdb_check_write_disable_wal, nullptr, | ||
| 1900 | rocksdb::WriteOptions().disableWAL); | ||
| 1901 | static MYSQL_THDVAR_BOOL(write_disable_wal_save, PLUGIN_VAR_INVISIBLE, | ||
| 1902 | "WriteOptions::disableWAL shadow", nullptr, nullptr, | ||
| 1903 | rocksdb::WriteOptions().disableWAL); | ||
| 1904 | |||
| 1905 | static MYSQL_THDVAR_BOOL( | ||
| 1906 | write_ignore_missing_column_families, | ||
| 1907 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1908 | "WriteOptions::ignore_missing_column_families for RocksDB", nullptr, | ||
| 1909 | nullptr, rocksdb::WriteOptions().ignore_missing_column_families); | ||
| 1910 | |||
| 1911 | static MYSQL_THDVAR_BOOL(skip_fill_cache, | ||
| 1912 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1913 | "Skip filling block cache on read requests", nullptr, | ||
| 1914 | nullptr, false); | ||
| 1915 | |||
| 1916 | static MYSQL_THDVAR_BOOL( | ||
| 1917 | unsafe_for_binlog, PLUGIN_VAR_RQCMDARG, | ||
| 1918 | "Allowing statement based binary logging which may break consistency", | ||
| 1919 | nullptr, nullptr, false); | ||
| 1920 | |||
| 1921 | static MYSQL_THDVAR_UINT(records_in_range, | ||
| 1922 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1923 | "Used to override the result of records_in_range(). " | ||
| 1924 | "Set to a positive number to override", | ||
| 1925 | nullptr, nullptr, 0, | ||
| 1926 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1927 | |||
| 1928 | static MYSQL_THDVAR_UINT(force_index_records_in_range, | ||
| 1929 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1930 | "Used to override the result of records_in_range() " | ||
| 1931 | "when FORCE INDEX is used.", | ||
| 1932 | nullptr, nullptr, 0, | ||
| 1933 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1934 | |||
| 1935 | static MYSQL_SYSVAR_UINT( | ||
| 1936 | debug_optimizer_n_rows, rocksdb_debug_optimizer_n_rows, | ||
| 1937 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR, | ||
| 1938 | "Test only to override rocksdb estimates of table size in a memtable", | ||
| 1939 | nullptr, nullptr, 0, /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1940 | |||
| 1941 | static MYSQL_SYSVAR_BOOL(force_compute_memtable_stats, | ||
| 1942 | rocksdb_force_compute_memtable_stats, | ||
| 1943 | PLUGIN_VAR_RQCMDARG, | ||
| 1944 | "Force to always compute memtable stats", nullptr, | ||
| 1945 | nullptr, true); | ||
| 1946 | |||
| 1947 | static MYSQL_SYSVAR_UINT( | ||
| 1948 | force_compute_memtable_stats_cachetime, | ||
| 1949 | rocksdb_force_compute_memtable_stats_cachetime, PLUGIN_VAR_RQCMDARG, | ||
| 1950 | "Time in usecs to cache memtable estimates", nullptr, nullptr, | ||
| 1951 | /* default */ RDB_DEFAULT_FORCE_COMPUTE_MEMTABLE_STATS_CACHETIME, | ||
| 1952 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1953 | |||
| 1954 | static MYSQL_SYSVAR_BOOL( | ||
| 1955 | debug_optimizer_no_zero_cardinality, | ||
| 1956 | rocksdb_debug_optimizer_no_zero_cardinality, PLUGIN_VAR_RQCMDARG, | ||
| 1957 | "In case if cardinality is zero, overrides it with some value", nullptr, | ||
| 1958 | nullptr, true); | ||
| 1959 | |||
| 1960 | static MYSQL_SYSVAR_UINT(debug_cardinality_multiplier, | ||
| 1961 | rocksdb_debug_cardinality_multiplier, | ||
| 1962 | PLUGIN_VAR_RQCMDARG, | ||
| 1963 | "Cardinality multiplier used in tests", nullptr, | ||
| 1964 | nullptr, /* default */ 2, | ||
| 1965 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1966 | |||
| 1967 | static MYSQL_SYSVAR_STR(compact_cf, rocksdb_compact_cf_name, | ||
| 1968 | PLUGIN_VAR_RQCMDARG, "Compact column family", | ||
| 1969 | rocksdb_compact_column_family, | ||
| 1970 | rocksdb_compact_column_family_stub, ""); | ||
| 1971 | |||
| 1972 | static MYSQL_SYSVAR_STR(delete_cf, rocksdb_delete_cf_name, PLUGIN_VAR_RQCMDARG, | ||
| 1973 | "Delete column family", rocksdb_delete_column_family, | ||
| 1974 | rocksdb_delete_column_family_stub, ""); | ||
| 1975 | |||
| 1976 | static MYSQL_SYSVAR_STR(create_checkpoint, rocksdb_checkpoint_name, | ||
| 1977 | PLUGIN_VAR_RQCMDARG, "Checkpoint directory", | ||
| 1978 | rocksdb_create_checkpoint_validate, | ||
| 1979 | rocksdb_create_checkpoint_update, ""); | ||
| 1980 | |||
| 1981 | static MYSQL_THDVAR_STR(create_temporary_checkpoint, | ||
| 1982 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC | | ||
| 1983 | PLUGIN_VAR_NOCMDOPT, | ||
| 1984 | "Temporary checkpoint directory", | ||
| 1985 | rocksdb_create_temporary_checkpoint_validate, nullptr, | ||
| 1986 | nullptr); | ||
| 1987 | |||
| 1988 | static MYSQL_SYSVAR_BOOL(signal_drop_index_thread, | ||
| 1989 | rocksdb_signal_drop_index_thread, PLUGIN_VAR_RQCMDARG, | ||
| 1990 | "Wake up drop index thread", nullptr, | ||
| 1991 | rocksdb_drop_index_wakeup_thread, false); | ||
| 1992 | |||
| 1993 | static MYSQL_SYSVAR_BOOL(pause_background_work, rocksdb_pause_background_work, | ||
| 1994 | PLUGIN_VAR_RQCMDARG, | ||
| 1995 | "Disable all rocksdb background operations", nullptr, | ||
| 1996 | rocksdb_set_pause_background_work, false); | ||
| 1997 | |||
| 1998 | static MYSQL_THDVAR_BOOL(disable_file_deletions, | ||
| 1999 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG, | ||
| 2000 | "Prevent file deletions", nullptr, | ||
| 2001 | rocksdb_disable_file_deletions_update, false); | ||
| 2002 | |||
| 2003 | static MYSQL_SYSVAR_BOOL( | ||
| 2004 | enable_ttl, rocksdb_enable_ttl, PLUGIN_VAR_RQCMDARG, | ||
| 2005 | "Enable expired TTL records to be dropped during compaction.", nullptr, | ||
| 2006 | nullptr, true); | ||
| 2007 | |||
| 2008 | static MYSQL_SYSVAR_BOOL( | ||
| 2009 | enable_ttl_read_filtering, rocksdb_enable_ttl_read_filtering, | ||
| 2010 | PLUGIN_VAR_RQCMDARG, | ||
| 2011 | "For tables with TTL, expired records are skipped/filtered out during " | ||
| 2012 | "processing and in query results. Disabling this will allow these records " | ||
| 2013 | "to be seen, but as a result rows may disappear in the middle of " | ||
| 2014 | "transactions as they are dropped during compaction. Use with caution.", | ||
| 2015 | nullptr, nullptr, true); | ||
| 2016 | |||
| 2017 | static MYSQL_SYSVAR_INT( | ||
| 2018 | debug_ttl_rec_ts, rocksdb_debug_ttl_rec_ts, PLUGIN_VAR_RQCMDARG, | ||
| 2019 | "For debugging purposes only. Overrides the TTL of records to " | ||
| 2020 | "now() + debug_ttl_rec_ts. The value can be +/- to simulate " | ||
| 2021 | "a record inserted in the past vs a record inserted in the 'future'. " | ||
| 2022 | "A value of 0 denotes that the variable is not set. This variable is a " | ||
| 2023 | "no-op in non-debug builds.", | ||
| 2024 | nullptr, nullptr, 0, /* min */ -3600, /* max */ 3600, 0); | ||
| 2025 | |||
| 2026 | static MYSQL_SYSVAR_INT( | ||
| 2027 | debug_ttl_snapshot_ts, rocksdb_debug_ttl_snapshot_ts, PLUGIN_VAR_RQCMDARG, | ||
| 2028 | "For debugging purposes only. Sets the snapshot during compaction to " | ||
| 2029 | "now() + debug_set_ttl_snapshot_ts. The value can be +/- to simulate " | ||
| 2030 | "a snapshot in the past vs a snapshot created in the 'future'. " | ||
| 2031 | "A value of 0 denotes that the variable is not set. This variable is a " | ||
| 2032 | "no-op in non-debug builds.", | ||
| 2033 | nullptr, nullptr, 0, /* min */ -3600, /* max */ 3600, 0); | ||
| 2034 | |||
| 2035 | static MYSQL_SYSVAR_INT( | ||
| 2036 | debug_ttl_read_filter_ts, rocksdb_debug_ttl_read_filter_ts, | ||
| 2037 | PLUGIN_VAR_RQCMDARG, | ||
| 2038 | "For debugging purposes only. Overrides the TTL read filtering time to " | ||
| 2039 | "time + debug_ttl_read_filter_ts. A value of 0 denotes that the variable " | ||
| 2040 | "is not set. This variable is a no-op in non-debug builds.", | ||
| 2041 | nullptr, nullptr, 0, /* min */ -3600, /* max */ 3600, 0); | ||
| 2042 | |||
| 2043 | static MYSQL_SYSVAR_BOOL( | ||
| 2044 | debug_ttl_ignore_pk, rocksdb_debug_ttl_ignore_pk, PLUGIN_VAR_RQCMDARG, | ||
| 2045 | "For debugging purposes only. If true, compaction filtering will not occur " | ||
| 2046 | "on PK TTL data. This variable is a no-op in non-debug builds.", | ||
| 2047 | nullptr, nullptr, false); | ||
| 2048 | |||
| 2049 | static MYSQL_SYSVAR_UINT( | ||
| 2050 | max_manual_compactions, rocksdb_max_manual_compactions, PLUGIN_VAR_RQCMDARG, | ||
| 2051 | "Maximum number of pending + ongoing number of manual compactions.", | ||
| 2052 | nullptr, nullptr, /* default */ 10, /* min */ 0, /* max */ UINT_MAX, 0); | ||
| 2053 | |||
| 2054 | static MYSQL_SYSVAR_BOOL( | ||
| 2055 | rollback_on_timeout, rocksdb_rollback_on_timeout, PLUGIN_VAR_OPCMDARG, | ||
| 2056 | "Whether to roll back the complete transaction or a single statement on " | ||
| 2057 | "lock wait timeout (a single statement by default)", | ||
| 2058 | NULL, NULL, false); | ||
| 2059 | |||
| 2060 | static MYSQL_SYSVAR_UINT( | ||
| 2061 | debug_manual_compaction_delay, rocksdb_debug_manual_compaction_delay, | ||
| 2062 | PLUGIN_VAR_RQCMDARG, | ||
| 2063 | "For debugging purposes only. Sleeping specified seconds " | ||
| 2064 | "for simulating long running compactions.", | ||
| 2065 | nullptr, nullptr, 0, /* min */ 0, /* max */ UINT_MAX, 0); | ||
| 2066 | |||
| 2067 | static MYSQL_SYSVAR_BOOL( | ||
| 2068 | reset_stats, rocksdb_reset_stats, PLUGIN_VAR_RQCMDARG, | ||
| 2069 | "Reset the RocksDB internal statistics without restarting the DB.", nullptr, | ||
| 2070 | rocksdb_set_reset_stats, false); | ||
| 2071 | |||
| 2072 | static MYSQL_SYSVAR_BOOL(ignore_unknown_options, rocksdb_ignore_unknown_options, | ||
| 2073 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 2074 | "Enable ignoring unknown options passed to RocksDB", | ||
| 2075 | nullptr, nullptr, true); | ||
| 2076 | |||
| 2077 | /* | ||
| 2078 | TODO(herman) - Both strict_collation_check and strict_collation_exceptions can | ||
| 2079 | be deprecated now that SKs support index lookups for all collations. | ||
| 2080 | */ | ||
| 2081 | static MYSQL_SYSVAR_BOOL(strict_collation_check, rocksdb_strict_collation_check, | ||
| 2082 | PLUGIN_VAR_RQCMDARG, | ||
| 2083 | "Enforce case sensitive collation for MyRocks indexes", | ||
| 2084 | nullptr, nullptr, true); | ||
| 2085 | |||
| 2086 | static MYSQL_SYSVAR_STR(strict_collation_exceptions, | ||
| 2087 | rocksdb_strict_collation_exceptions, | ||
| 2088 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 2089 | "Regex that describes set of tables that are excluded " | ||
| 2090 | "from the case sensitive collation enforcement", | ||
| 2091 | nullptr, rocksdb_set_collation_exception_list, ""); | ||
| 2092 | |||
| 2093 | static MYSQL_SYSVAR_BOOL(collect_sst_properties, rocksdb_collect_sst_properties, | ||
| 2094 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 2095 | "Enables collecting SST file properties on each flush", | ||
| 2096 | nullptr, nullptr, rocksdb_collect_sst_properties); | ||
| 2097 | |||
| 2098 | static MYSQL_SYSVAR_BOOL( | ||
| 2099 | force_flush_memtable_now, rocksdb_force_flush_memtable_now_var, | ||
| 2100 | PLUGIN_VAR_RQCMDARG, | ||
| 2101 | "Forces memstore flush which may block all write requests so be careful", | ||
| 2102 | rocksdb_force_flush_memtable_now, rocksdb_force_flush_memtable_now_stub, | ||
| 2103 | true); | ||
| 2104 | |||
| 2105 | static MYSQL_SYSVAR_BOOL( | ||
| 2106 | force_flush_memtable_and_lzero_now, | ||
| 2107 | rocksdb_force_flush_memtable_and_lzero_now_var, PLUGIN_VAR_RQCMDARG, | ||
| 2108 | "Acts similar to force_flush_memtable_now, but also compacts all L0 files.", | ||
| 2109 | rocksdb_force_flush_memtable_and_lzero_now, | ||
| 2110 | rocksdb_force_flush_memtable_and_lzero_now_stub, false); | ||
| 2111 | |||
| 2112 | static MYSQL_SYSVAR_BOOL(cancel_manual_compactions, | ||
| 2113 | rocksdb_cancel_manual_compactions_var, | ||
| 2114 | PLUGIN_VAR_RQCMDARG, | ||
| 2115 | "Cancelling all ongoing manual compactions.", | ||
| 2116 | rocksdb_cancel_manual_compactions, | ||
| 2117 | rocksdb_cancel_manual_compactions_stub, false); | ||
| 2118 | |||
| 2119 | static MYSQL_SYSVAR_UINT( | ||
| 2120 | seconds_between_stat_computes, rocksdb_seconds_between_stat_computes, | ||
| 2121 | PLUGIN_VAR_RQCMDARG, | ||
| 2122 | "Sets a number of seconds to wait between optimizer stats recomputation. " | ||
| 2123 | "Only changed indexes will be refreshed.", | ||
| 2124 | nullptr, nullptr, rocksdb_seconds_between_stat_computes, | ||
| 2125 | /* min */ 0L, /* max */ UINT_MAX, 0); | ||
| 2126 | |||
| 2127 | static MYSQL_SYSVAR_LONGLONG(compaction_sequential_deletes, | ||
| 2128 | rocksdb_compaction_sequential_deletes, | ||
| 2129 | PLUGIN_VAR_RQCMDARG, | ||
| 2130 | "RocksDB will trigger compaction for the file if " | ||
| 2131 | "it has more than this number sequential deletes " | ||
| 2132 | "per window", | ||
| 2133 | nullptr, rocksdb_set_compaction_options, | ||
| 2134 | DEFAULT_COMPACTION_SEQUENTIAL_DELETES, | ||
| 2135 | /* min */ 0L, | ||
| 2136 | /* max */ MAX_COMPACTION_SEQUENTIAL_DELETES, 0); | ||
| 2137 | |||
| 2138 | static MYSQL_SYSVAR_LONGLONG( | ||
| 2139 | compaction_sequential_deletes_window, | ||
| 2140 | rocksdb_compaction_sequential_deletes_window, PLUGIN_VAR_RQCMDARG, | ||
| 2141 | "Size of the window for counting rocksdb_compaction_sequential_deletes", | ||
| 2142 | nullptr, rocksdb_set_compaction_options, | ||
| 2143 | DEFAULT_COMPACTION_SEQUENTIAL_DELETES_WINDOW, | ||
| 2144 | /* min */ 0L, /* max */ MAX_COMPACTION_SEQUENTIAL_DELETES_WINDOW, 0); | ||
| 2145 | |||
| 2146 | static MYSQL_SYSVAR_LONGLONG( | ||
| 2147 | compaction_sequential_deletes_file_size, | ||
| 2148 | rocksdb_compaction_sequential_deletes_file_size, PLUGIN_VAR_RQCMDARG, | ||
| 2149 | "Minimum file size required for compaction_sequential_deletes", nullptr, | ||
| 2150 | rocksdb_set_compaction_options, 0L, | ||
| 2151 | /* min */ -1L, /* max */ LLONG_MAX, 0); | ||
| 2152 | |||
| 2153 | static MYSQL_SYSVAR_BOOL( | ||
| 2154 | compaction_sequential_deletes_count_sd, | ||
| 2155 | rocksdb_compaction_sequential_deletes_count_sd, PLUGIN_VAR_RQCMDARG, | ||
| 2156 | "Counting SingleDelete as rocksdb_compaction_sequential_deletes", nullptr, | ||
| 2157 | nullptr, rocksdb_compaction_sequential_deletes_count_sd); | ||
| 2158 | |||
| 2159 | static MYSQL_SYSVAR_BOOL( | ||
| 2160 | print_snapshot_conflict_queries, rocksdb_print_snapshot_conflict_queries, | ||
| 2161 | PLUGIN_VAR_RQCMDARG, | ||
| 2162 | "Logging queries that got snapshot conflict errors into *.err log", nullptr, | ||
| 2163 | nullptr, rocksdb_print_snapshot_conflict_queries); | ||
| 2164 | |||
| 2165 | static MYSQL_THDVAR_INT(checksums_pct, | ||
| 2166 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 2167 | "How many percentages of rows to be checksummed", | ||
| 2168 | nullptr, nullptr, RDB_MAX_CHECKSUMS_PCT, | ||
| 2169 | /* min */ 0, /* max */ RDB_MAX_CHECKSUMS_PCT, 0); | ||
| 2170 | |||
| 2171 | static MYSQL_THDVAR_BOOL(store_row_debug_checksums, | ||
| 2172 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 2173 | "Include checksums when writing index/table records", | ||
| 2174 | nullptr, nullptr, false /* default value */); | ||
| 2175 | |||
| 2176 | static MYSQL_THDVAR_BOOL(verify_row_debug_checksums, | ||
| 2177 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 2178 | "Verify checksums when reading index/table records", | ||
| 2179 | nullptr, nullptr, false /* default value */); | ||
| 2180 | |||
| 2181 | static MYSQL_THDVAR_BOOL(master_skip_tx_api, | ||
| 2182 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 2183 | "Skipping holding any lock on row access. " | ||
| 2184 | "Not effective on slave.", | ||
| 2185 | nullptr, nullptr, false); | ||
| 2186 | |||
| 2187 | #if defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 2188 | static MYSQL_SYSVAR_UINT( | ||
| 2189 | validate_tables, rocksdb_validate_tables, | ||
| 2190 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 2191 | "Verify all DD tables match all RocksDB tables (0 means no verification, " | ||
| 2192 | "1 means verify and fail on error, and 2 means verify but continue", | ||
| 2193 | nullptr, nullptr, 1 /* default value */, 0 /* min value */, | ||
| 2194 | 2 /* max value */, 0); | ||
| 2195 | #endif // defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && | ||
| 2196 | // ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 2197 | |||
| 2198 | static MYSQL_SYSVAR_STR(datadir, rocksdb_datadir, | ||
| 2199 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 2200 | "RocksDB data directory", nullptr, nullptr, | ||
| 2201 | "./.rocksdb"); | ||
| 2202 | |||
| 2203 | static MYSQL_SYSVAR_STR(fs_uri, rocksdb_fs_uri, | ||
| 2204 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 2205 | "Custom filesystem URI", nullptr, nullptr, nullptr); | ||
| 2206 | |||
| 2207 | static MYSQL_SYSVAR_UINT( | ||
| 2208 | table_stats_sampling_pct, rocksdb_table_stats_sampling_pct, | ||
| 2209 | PLUGIN_VAR_RQCMDARG, | ||
| 2210 | "Percentage of entries to sample when collecting statistics about table " | ||
| 2211 | "properties. Specify either 0 to sample everything or percentage " | ||
| 2212 | "[" STRINGIFY_ARG(RDB_TBL_STATS_SAMPLE_PCT_MIN) ".." STRINGIFY_ARG( | ||
| 2213 | RDB_TBL_STATS_SAMPLE_PCT_MAX) "]. " | ||
| 2214 | "By default " STRINGIFY_ARG( | ||
| 2215 | RDB_DEFAULT_TBL_STATS_SAMPLE_PCT) "% " | ||
| 2216 | "of" | ||
| 2217 | " e" | ||
| 2218 | "nt" | ||
| 2219 | "ri" | ||
| 2220 | "es" | ||
| 2221 | " a" | ||
| 2222 | "re" | ||
| 2223 | " " | ||
| 2224 | "sa" | ||
| 2225 | "mp" | ||
| 2226 | "le" | ||
| 2227 | "d" | ||
| 2228 | ".", | ||
| 2229 | nullptr, rocksdb_set_table_stats_sampling_pct, /* default */ | ||
| 2230 | RDB_DEFAULT_TBL_STATS_SAMPLE_PCT, /* everything */ 0, | ||
| 2231 | /* max */ RDB_TBL_STATS_SAMPLE_PCT_MAX, 0); | ||
| 2232 | |||
| 2233 | static MYSQL_SYSVAR_UINT(table_stats_recalc_threshold_pct, | ||
| 2234 | rocksdb_table_stats_recalc_threshold_pct, | ||
| 2235 | PLUGIN_VAR_RQCMDARG, | ||
| 2236 | "Percentage of number of modified rows over total " | ||
| 2237 | "number of rows to trigger stats recalculation", | ||
| 2238 | nullptr, nullptr, /* default */ | ||
| 2239 | rocksdb_table_stats_recalc_threshold_pct, | ||
| 2240 | /* everything */ 0, | ||
| 2241 | /* max */ RDB_TBL_STATS_RECALC_THRESHOLD_PCT_MAX, 0); | ||
| 2242 | |||
| 2243 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 2244 | table_stats_recalc_threshold_count, | ||
| 2245 | rocksdb_table_stats_recalc_threshold_count, PLUGIN_VAR_RQCMDARG, | ||
| 2246 | "Number of modified rows to trigger stats recalculation", nullptr, | ||
| 2247 | nullptr, /* default */ | ||
| 2248 | rocksdb_table_stats_recalc_threshold_count, | ||
| 2249 | /* everything */ 0, | ||
| 2250 | /* max */ UINT64_MAX, 0); | ||
| 2251 | |||
| 2252 | static MYSQL_SYSVAR_INT( | ||
| 2253 | table_stats_background_thread_nice_value, | ||
| 2254 | rocksdb_table_stats_background_thread_nice_value, PLUGIN_VAR_RQCMDARG, | ||
| 2255 | "nice value for index stats", rocksdb_index_stats_thread_renice, nullptr, | ||
| 2256 | /* default */ rocksdb_table_stats_background_thread_nice_value, | ||
| 2257 | /* min */ THREAD_PRIO_MIN, /* max */ THREAD_PRIO_MAX, 0); | ||
| 2258 | |||
| 2259 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 2260 | table_stats_max_num_rows_scanned, rocksdb_table_stats_max_num_rows_scanned, | ||
| 2261 | PLUGIN_VAR_RQCMDARG, | ||
| 2262 | "The maximum number of rows to scan in table scan based " | ||
| 2263 | "cardinality calculation", | ||
| 2264 | nullptr, nullptr, /* default */ | ||
| 2265 | 0, /* everything */ 0, | ||
| 2266 | /* max */ UINT64_MAX, 0); | ||
| 2267 | |||
| 2268 | static MYSQL_SYSVAR_UINT( | ||
| 2269 | stats_recalc_rate, rocksdb_stats_recalc_rate, PLUGIN_VAR_RQCMDARG, | ||
| 2270 | "The number of indexes per second to recalculate statistics for. 0 to " | ||
| 2271 | "disable background recalculation.", | ||
| 2272 | nullptr, nullptr, 0 /* default value */, 0 /* min value */, | ||
| 2273 | UINT_MAX /* max value */, 0); | ||
| 2274 | |||
| 2275 | static MYSQL_SYSVAR_BOOL(table_stats_use_table_scan, | ||
| 2276 | rocksdb_table_stats_use_table_scan, | ||
| 2277 | PLUGIN_VAR_RQCMDARG, | ||
| 2278 | "Enable table scan based index calculation.", nullptr, | ||
| 2279 | rocksdb_update_table_stats_use_table_scan, | ||
| 2280 | rocksdb_table_stats_use_table_scan); | ||
| 2281 | |||
| 2282 | static MYSQL_SYSVAR_BOOL( | ||
| 2283 | large_prefix, rocksdb_large_prefix, PLUGIN_VAR_RQCMDARG, | ||
| 2284 | "Support large index prefix length of 3072 bytes. If off, the maximum " | ||
| 2285 | "index prefix length is 767.", | ||
| 2286 | nullptr, nullptr, true); | ||
| 2287 | |||
| 2288 | static MYSQL_SYSVAR_BOOL( | ||
| 2289 | allow_to_start_after_corruption, rocksdb_allow_to_start_after_corruption, | ||
| 2290 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 2291 | "Allow server to start successfully when RocksDB corruption is detected.", | ||
| 2292 | nullptr, nullptr, false); | ||
| 2293 | |||
| 2294 | static MYSQL_SYSVAR_BOOL(error_on_suboptimal_collation, | ||
| 2295 | rocksdb_error_on_suboptimal_collation, | ||
| 2296 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 2297 | "Raise an error instead of warning if a sub-optimal " | ||
| 2298 | "collation is used", | ||
| 2299 | nullptr, nullptr, false); | ||
| 2300 | |||
| 2301 | static MYSQL_SYSVAR_BOOL( | ||
| 2302 | no_create_column_family, rocksdb_no_create_column_family, | ||
| 2303 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 2304 | "Do not allow creation of new Column Families through index comments.", | ||
| 2305 | nullptr, nullptr, false); | ||
| 2306 | |||
| 2307 | static MYSQL_SYSVAR_BOOL( | ||
| 2308 | enable_insert_with_update_caching, | ||
| 2309 | rocksdb_enable_insert_with_update_caching, PLUGIN_VAR_OPCMDARG, | ||
| 2310 | "Whether to enable optimization where we cache the read from a failed " | ||
| 2311 | "insertion attempt in INSERT ON DUPLICATE KEY UPDATE", | ||
| 2312 | nullptr, nullptr, true); | ||
| 2313 | |||
| 2314 | static MYSQL_SYSVAR_STR( | ||
| 2315 | trace_block_cache_access, rocksdb_block_cache_trace_options_str, | ||
| 2316 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 2317 | "Block cache trace option string. The format is " | ||
| 2318 | "sampling_frequency:max_trace_file_size:trace_file_name. " | ||
| 2319 | "sampling_frequency and max_trace_file_size are positive integers. The " | ||
| 2320 | "block accesses are saved to the " | ||
| 2321 | "rocksdb_datadir/block_cache_traces/trace_file_name.", | ||
| 2322 | rocksdb_trace_block_cache_access, nullptr, ""); | ||
| 2323 | |||
| 2324 | static MYSQL_SYSVAR_STR( | ||
| 2325 | trace_queries, rocksdb_trace_options_str, | ||
| 2326 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 2327 | "Trace option string. The format is " | ||
| 2328 | "sampling_frequency:max_trace_file_size:trace_file_name. " | ||
| 2329 | "sampling_frequency and max_trace_file_size are positive integers. The " | ||
| 2330 | "queries are saved to the " | ||
| 2331 | "rocksdb_datadir/queries_traces/trace_file_name.", | ||
| 2332 | rocksdb_trace_queries, nullptr, ""); | ||
| 2333 | |||
| 2334 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 2335 | max_compaction_history, rocksdb_max_compaction_history, PLUGIN_VAR_OPCMDARG, | ||
| 2336 | "Track history for at most this many completed compactions. " | ||
| 2337 | "The history is in the INFORMATION_SCHEMA.ROCKSDB_COMPACTION_HISTORY " | ||
| 2338 | "table.", | ||
| 2339 | nullptr, rocksdb_max_compaction_history_update, | ||
| 2340 | RDB_DEFAULT_MAX_COMPACTION_HISTORY, 0ULL /* min */, UINT64_MAX /* max */, | ||
| 2341 | 0 /* blk */); | ||
| 2342 | |||
| 2343 | static MYSQL_SYSVAR_BOOL(skip_locks_if_skip_unique_check, | ||
| 2344 | rocksdb_skip_locks_if_skip_unique_check, | ||
| 2345 | PLUGIN_VAR_RQCMDARG, | ||
| 2346 | "Skip row locking when unique checks are disabled.", | ||
| 2347 | nullptr, nullptr, false); | ||
| 2348 | |||
| 2349 | static MYSQL_SYSVAR_BOOL( | ||
| 2350 | alter_column_default_inplace, rocksdb_alter_column_default_inplace, | ||
| 2351 | PLUGIN_VAR_RQCMDARG, | ||
| 2352 | "Allow inplace alter for alter column default operation", nullptr, nullptr, | ||
| 2353 | true); | ||
| 2354 | |||
| 2355 | static MYSQL_THDVAR_ULONGLONG( | ||
| 2356 | partial_index_sort_max_mem, PLUGIN_VAR_RQCMDARG, | ||
| 2357 | "Maximum memory to use when sorting an unmaterialized group for partial " | ||
| 2358 | "indexes. 0 means no limit.", | ||
| 2359 | nullptr, nullptr, | ||
| 2360 | /* default */ 0, /* min */ 0, /* max */ SIZE_T_MAX, 1); | ||
| 2361 | |||
| 2362 | static MYSQL_SYSVAR_BOOL(instant_ddl, rocksdb_instant_ddl, PLUGIN_VAR_RQCMDARG, | ||
| 2363 | "Allow instant ddl during alter table", nullptr, | ||
| 2364 | nullptr, false); | ||
| 2365 | |||
| 2366 | static MYSQL_SYSVAR_BOOL(enable_tmp_table, rocksdb_enable_tmp_table, | ||
| 2367 | PLUGIN_VAR_READONLY, "Allow rocksdb tmp tables", | ||
| 2368 | nullptr, nullptr, false); | ||
| 2369 | |||
| 2370 | static const int ROCKSDB_ASSUMED_KEY_VALUE_DISK_SIZE = 100; | ||
| 2371 | |||
| 2372 | static struct SYS_VAR *rocksdb_system_variables[] = { | ||
| 2373 | MYSQL_SYSVAR(lock_wait_timeout), | ||
| 2374 | MYSQL_SYSVAR(deadlock_detect), | ||
| 2375 | MYSQL_SYSVAR(deadlock_detect_depth), | ||
| 2376 | MYSQL_SYSVAR(commit_time_batch_for_recovery), | ||
| 2377 | MYSQL_SYSVAR(max_row_locks), | ||
| 2378 | MYSQL_SYSVAR(write_batch_max_bytes), | ||
| 2379 | MYSQL_SYSVAR(write_batch_flush_threshold), | ||
| 2380 | MYSQL_SYSVAR(lock_scanned_rows), | ||
| 2381 | MYSQL_SYSVAR(bulk_load), | ||
| 2382 | MYSQL_SYSVAR(bulk_load_allow_sk), | ||
| 2383 | MYSQL_SYSVAR(bulk_load_allow_unsorted), | ||
| 2384 | MYSQL_SYSVAR(trace_sst_api), | ||
| 2385 | MYSQL_SYSVAR(commit_in_the_middle), | ||
| 2386 | MYSQL_SYSVAR(blind_delete_primary_key), | ||
| 2387 | MYSQL_SYSVAR(enable_iterate_bounds), | ||
| 2388 | #if defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 2389 | MYSQL_SYSVAR(read_free_rpl_tables), | ||
| 2390 | MYSQL_SYSVAR(read_free_rpl), | ||
| 2391 | #endif // defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 2392 | MYSQL_SYSVAR(rpl_skip_tx_api), | ||
| 2393 | MYSQL_SYSVAR(bulk_load_size), | ||
| 2394 | MYSQL_SYSVAR(bulk_load_partial_index), | ||
| 2395 | MYSQL_SYSVAR(merge_buf_size), | ||
| 2396 | MYSQL_SYSVAR(enable_bulk_load_api), | ||
| 2397 | MYSQL_SYSVAR(enable_pipelined_write), | ||
| 2398 | MYSQL_SYSVAR(enable_remove_orphaned_dropped_cfs), | ||
| 2399 | MYSQL_SYSVAR(tmpdir), | ||
| 2400 | MYSQL_SYSVAR(merge_combine_read_size), | ||
| 2401 | MYSQL_SYSVAR(merge_tmp_file_removal_delay_ms), | ||
| 2402 | MYSQL_SYSVAR(skip_bloom_filter_on_read), | ||
| 2403 | |||
| 2404 | MYSQL_SYSVAR(create_if_missing), | ||
| 2405 | MYSQL_SYSVAR(concurrent_prepare), | ||
| 2406 | MYSQL_SYSVAR(two_write_queues), | ||
| 2407 | MYSQL_SYSVAR(manual_wal_flush), | ||
| 2408 | MYSQL_SYSVAR(write_policy), | ||
| 2409 | MYSQL_SYSVAR(create_missing_column_families), | ||
| 2410 | MYSQL_SYSVAR(error_if_exists), | ||
| 2411 | MYSQL_SYSVAR(paranoid_checks), | ||
| 2412 | MYSQL_SYSVAR(rate_limiter_bytes_per_sec), | ||
| 2413 | MYSQL_SYSVAR(sst_mgr_rate_bytes_per_sec), | ||
| 2414 | MYSQL_SYSVAR(delayed_write_rate), | ||
| 2415 | MYSQL_SYSVAR(max_latest_deadlocks), | ||
| 2416 | MYSQL_SYSVAR(info_log_level), | ||
| 2417 | MYSQL_SYSVAR(max_open_files), | ||
| 2418 | MYSQL_SYSVAR(max_total_wal_size), | ||
| 2419 | MYSQL_SYSVAR(use_fsync), | ||
| 2420 | MYSQL_SYSVAR(wal_dir), | ||
| 2421 | MYSQL_SYSVAR(persistent_cache_path), | ||
| 2422 | MYSQL_SYSVAR(persistent_cache_size_mb), | ||
| 2423 | MYSQL_SYSVAR(wsenv_path), | ||
| 2424 | MYSQL_SYSVAR(fault_injection_options), | ||
| 2425 | MYSQL_SYSVAR(delete_obsolete_files_period_micros), | ||
| 2426 | MYSQL_SYSVAR(max_background_jobs), | ||
| 2427 | MYSQL_SYSVAR(max_background_flushes), | ||
| 2428 | MYSQL_SYSVAR(max_background_compactions), | ||
| 2429 | MYSQL_SYSVAR(max_bottom_pri_background_compactions), | ||
| 2430 | MYSQL_SYSVAR(max_log_file_size), | ||
| 2431 | MYSQL_SYSVAR(max_subcompactions), | ||
| 2432 | MYSQL_SYSVAR(log_file_time_to_roll), | ||
| 2433 | MYSQL_SYSVAR(keep_log_file_num), | ||
| 2434 | MYSQL_SYSVAR(max_manifest_file_size), | ||
| 2435 | MYSQL_SYSVAR(table_cache_numshardbits), | ||
| 2436 | MYSQL_SYSVAR(wal_ttl_seconds), | ||
| 2437 | MYSQL_SYSVAR(wal_size_limit_mb), | ||
| 2438 | MYSQL_SYSVAR(manifest_preallocation_size), | ||
| 2439 | MYSQL_SYSVAR(use_direct_reads), | ||
| 2440 | MYSQL_SYSVAR(use_direct_io_for_flush_and_compaction), | ||
| 2441 | MYSQL_SYSVAR(allow_mmap_reads), | ||
| 2442 | MYSQL_SYSVAR(allow_mmap_writes), | ||
| 2443 | MYSQL_SYSVAR(is_fd_close_on_exec), | ||
| 2444 | MYSQL_SYSVAR(stats_dump_period_sec), | ||
| 2445 | MYSQL_SYSVAR(advise_random_on_open), | ||
| 2446 | MYSQL_SYSVAR(db_write_buffer_size), | ||
| 2447 | MYSQL_SYSVAR(use_adaptive_mutex), | ||
| 2448 | MYSQL_SYSVAR(bytes_per_sync), | ||
| 2449 | MYSQL_SYSVAR(wal_bytes_per_sync), | ||
| 2450 | MYSQL_SYSVAR(enable_thread_tracking), | ||
| 2451 | MYSQL_SYSVAR(perf_context_level), | ||
| 2452 | MYSQL_SYSVAR(wal_recovery_mode), | ||
| 2453 | MYSQL_SYSVAR(track_and_verify_wals_in_manifest), | ||
| 2454 | MYSQL_SYSVAR(stats_level), | ||
| 2455 | MYSQL_SYSVAR(access_hint_on_compaction_start), | ||
| 2456 | MYSQL_SYSVAR(compaction_readahead_size), | ||
| 2457 | MYSQL_SYSVAR(allow_concurrent_memtable_write), | ||
| 2458 | MYSQL_SYSVAR(enable_write_thread_adaptive_yield), | ||
| 2459 | |||
| 2460 | MYSQL_SYSVAR(block_cache_size), | ||
| 2461 | MYSQL_SYSVAR(sim_cache_size), | ||
| 2462 | MYSQL_SYSVAR(cache_high_pri_pool_ratio), | ||
| 2463 | MYSQL_SYSVAR(cache_dump), | ||
| 2464 | MYSQL_SYSVAR(cache_index_and_filter_blocks), | ||
| 2465 | MYSQL_SYSVAR(cache_index_and_filter_with_high_priority), | ||
| 2466 | MYSQL_SYSVAR(pin_l0_filter_and_index_blocks_in_cache), | ||
| 2467 | MYSQL_SYSVAR(index_type), | ||
| 2468 | MYSQL_SYSVAR(no_block_cache), | ||
| 2469 | MYSQL_SYSVAR(block_size), | ||
| 2470 | MYSQL_SYSVAR(block_size_deviation), | ||
| 2471 | MYSQL_SYSVAR(block_restart_interval), | ||
| 2472 | MYSQL_SYSVAR(whole_key_filtering), | ||
| 2473 | |||
| 2474 | MYSQL_SYSVAR(default_cf_options), | ||
| 2475 | MYSQL_SYSVAR(override_cf_options), | ||
| 2476 | MYSQL_SYSVAR(update_cf_options), | ||
| 2477 | MYSQL_SYSVAR(use_default_sk_cf), | ||
| 2478 | MYSQL_SYSVAR(allow_unsafe_alter), | ||
| 2479 | |||
| 2480 | MYSQL_SYSVAR(flush_log_at_trx_commit), | ||
| 2481 | MYSQL_SYSVAR(write_disable_wal), | ||
| 2482 | MYSQL_SYSVAR(write_disable_wal_save), | ||
| 2483 | MYSQL_SYSVAR(write_ignore_missing_column_families), | ||
| 2484 | |||
| 2485 | MYSQL_SYSVAR(skip_fill_cache), | ||
| 2486 | MYSQL_SYSVAR(unsafe_for_binlog), | ||
| 2487 | |||
| 2488 | MYSQL_SYSVAR(records_in_range), | ||
| 2489 | MYSQL_SYSVAR(force_index_records_in_range), | ||
| 2490 | MYSQL_SYSVAR(debug_optimizer_n_rows), | ||
| 2491 | MYSQL_SYSVAR(force_compute_memtable_stats), | ||
| 2492 | MYSQL_SYSVAR(force_compute_memtable_stats_cachetime), | ||
| 2493 | MYSQL_SYSVAR(debug_optimizer_no_zero_cardinality), | ||
| 2494 | MYSQL_SYSVAR(debug_cardinality_multiplier), | ||
| 2495 | |||
| 2496 | MYSQL_SYSVAR(compact_cf), | ||
| 2497 | MYSQL_SYSVAR(delete_cf), | ||
| 2498 | MYSQL_SYSVAR(signal_drop_index_thread), | ||
| 2499 | MYSQL_SYSVAR(pause_background_work), | ||
| 2500 | MYSQL_SYSVAR(ignore_unknown_options), | ||
| 2501 | MYSQL_SYSVAR(strict_collation_check), | ||
| 2502 | MYSQL_SYSVAR(strict_collation_exceptions), | ||
| 2503 | MYSQL_SYSVAR(collect_sst_properties), | ||
| 2504 | MYSQL_SYSVAR(force_flush_memtable_now), | ||
| 2505 | MYSQL_SYSVAR(force_flush_memtable_and_lzero_now), | ||
| 2506 | MYSQL_SYSVAR(cancel_manual_compactions), | ||
| 2507 | MYSQL_SYSVAR(enable_ttl), | ||
| 2508 | MYSQL_SYSVAR(enable_ttl_read_filtering), | ||
| 2509 | MYSQL_SYSVAR(debug_ttl_rec_ts), | ||
| 2510 | MYSQL_SYSVAR(debug_ttl_snapshot_ts), | ||
| 2511 | MYSQL_SYSVAR(debug_ttl_read_filter_ts), | ||
| 2512 | MYSQL_SYSVAR(debug_ttl_ignore_pk), | ||
| 2513 | MYSQL_SYSVAR(reset_stats), | ||
| 2514 | MYSQL_SYSVAR(seconds_between_stat_computes), | ||
| 2515 | |||
| 2516 | MYSQL_SYSVAR(compaction_sequential_deletes), | ||
| 2517 | MYSQL_SYSVAR(compaction_sequential_deletes_window), | ||
| 2518 | MYSQL_SYSVAR(compaction_sequential_deletes_file_size), | ||
| 2519 | MYSQL_SYSVAR(compaction_sequential_deletes_count_sd), | ||
| 2520 | MYSQL_SYSVAR(print_snapshot_conflict_queries), | ||
| 2521 | |||
| 2522 | MYSQL_SYSVAR(datadir), | ||
| 2523 | MYSQL_SYSVAR(fs_uri), | ||
| 2524 | MYSQL_SYSVAR(create_checkpoint), | ||
| 2525 | MYSQL_SYSVAR(create_temporary_checkpoint), | ||
| 2526 | MYSQL_SYSVAR(disable_file_deletions), | ||
| 2527 | |||
| 2528 | MYSQL_SYSVAR(checksums_pct), | ||
| 2529 | MYSQL_SYSVAR(store_row_debug_checksums), | ||
| 2530 | MYSQL_SYSVAR(verify_row_debug_checksums), | ||
| 2531 | MYSQL_SYSVAR(master_skip_tx_api), | ||
| 2532 | |||
| 2533 | #if defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 2534 | MYSQL_SYSVAR(validate_tables), | ||
| 2535 | #endif // defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && | ||
| 2536 | // ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 2537 | MYSQL_SYSVAR(table_stats_sampling_pct), | ||
| 2538 | MYSQL_SYSVAR(table_stats_recalc_threshold_pct), | ||
| 2539 | MYSQL_SYSVAR(table_stats_recalc_threshold_count), | ||
| 2540 | MYSQL_SYSVAR(table_stats_max_num_rows_scanned), | ||
| 2541 | MYSQL_SYSVAR(table_stats_use_table_scan), | ||
| 2542 | MYSQL_SYSVAR(table_stats_background_thread_nice_value), | ||
| 2543 | |||
| 2544 | MYSQL_SYSVAR(large_prefix), | ||
| 2545 | MYSQL_SYSVAR(allow_to_start_after_corruption), | ||
| 2546 | MYSQL_SYSVAR(error_on_suboptimal_collation), | ||
| 2547 | MYSQL_SYSVAR(no_create_column_family), | ||
| 2548 | MYSQL_SYSVAR(stats_recalc_rate), | ||
| 2549 | MYSQL_SYSVAR(debug_manual_compaction_delay), | ||
| 2550 | MYSQL_SYSVAR(max_manual_compactions), | ||
| 2551 | MYSQL_SYSVAR(manual_compaction_threads), | ||
| 2552 | MYSQL_SYSVAR(manual_compaction_bottommost_level), | ||
| 2553 | MYSQL_SYSVAR(rollback_on_timeout), | ||
| 2554 | |||
| 2555 | MYSQL_SYSVAR(enable_insert_with_update_caching), | ||
| 2556 | MYSQL_SYSVAR(trace_block_cache_access), | ||
| 2557 | MYSQL_SYSVAR(trace_queries), | ||
| 2558 | MYSQL_SYSVAR(max_compaction_history), | ||
| 2559 | MYSQL_SYSVAR(skip_locks_if_skip_unique_check), | ||
| 2560 | MYSQL_SYSVAR(alter_column_default_inplace), | ||
| 2561 | MYSQL_SYSVAR(partial_index_sort_max_mem), | ||
| 2562 | MYSQL_SYSVAR(instant_ddl), | ||
| 2563 | MYSQL_SYSVAR(enable_tmp_table), | ||
| 2564 | nullptr}; | ||
| 2565 | |||
| 2566 | 48154 | static bool is_tmp_table(const std::string &tablename) { | |
| 2567 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 47968 times.
|
48154 | if (tablename.find(TMP_SCHEMA_NAME) == 0) { |
| 2568 | // should land this case only if rocksdb_enable_tmp_table is enabled. | ||
| 2569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 186 times.
|
186 | assert(rocksdb_enable_tmp_table); |
| 2570 | 186 | return true; | |
| 2571 | } else { | ||
| 2572 | 47968 | return false; | |
| 2573 | } | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | 1227 | static int rocksdb_compact_column_family(THD *const thd, | |
| 2577 | struct SYS_VAR *const var, | ||
| 2578 | void *const var_ptr, | ||
| 2579 | struct st_mysql_value *const value) { | ||
| 2580 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 2581 | 1227 | int len = sizeof(buff); | |
| 2582 | |||
| 2583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1227 times.
|
1227 | assert(value != nullptr); |
| 2584 | |||
| 2585 |
2/4✓ Branch 0 taken 1227 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1227 times.
✗ Branch 3 not taken.
|
1227 | if (const char *const cf = value->val_str(value, buff, &len)) { |
| 2586 |
5/8✓ Branch 0 taken 1227 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1224 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
|
1227 | DBUG_EXECUTE_IF("rocksdb_compact_column_family", { |
| 2587 | static constexpr char act[] = | ||
| 2588 | "now signal ready_to_mark_cf_dropped_in_compact_column_family " | ||
| 2589 | "wait_for mark_cf_dropped_done_in_compact_column_family"; | ||
| 2590 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 2591 | }); | ||
| 2592 | |||
| 2593 |
1/2✓ Branch 0 taken 1227 times.
✗ Branch 1 not taken.
|
1227 | std::string cf_name = std::string(cf); |
| 2594 | // use rocksdb_compact_cf="" or "default" to compact default CF | ||
| 2595 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1226 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1227 | if (cf_name.empty()) cf_name = DEFAULT_CF_NAME; |
| 2596 | |||
| 2597 |
1/2✓ Branch 0 taken 1227 times.
✗ Branch 1 not taken.
|
1227 | auto cfh = cf_manager.get_cf(cf_name); |
| 2598 |
5/6✓ Branch 0 taken 1213 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 1213 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1213 times.
✓ Branch 5 taken 14 times.
|
1227 | if (cfh != nullptr && rdb != nullptr) { |
| 2599 | rocksdb::BottommostLevelCompaction bottommost_level_compaction = | ||
| 2600 |
1/2✓ Branch 0 taken 1213 times.
✗ Branch 1 not taken.
|
1213 | (rocksdb::BottommostLevelCompaction)THDVAR( |
| 2601 | thd, manual_compaction_bottommost_level); | ||
| 2602 | |||
| 2603 |
1/2✓ Branch 0 taken 1213 times.
✗ Branch 1 not taken.
|
1213 | int mc_id = rdb_mc_thread.request_manual_compaction( |
| 2604 |
1/2✓ Branch 0 taken 1213 times.
✗ Branch 1 not taken.
|
1213 | cfh, nullptr, nullptr, THDVAR(thd, manual_compaction_threads), |
| 2605 | 1213 | bottommost_level_compaction); | |
| 2606 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1207 times.
|
1213 | if (mc_id == -1) { |
| 2607 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_INTERNAL_ERROR, MYF(0), |
| 2608 | "Can't schedule more manual compactions. " | ||
| 2609 | "Increase rocksdb_max_manual_compactions or stop issuing " | ||
| 2610 | "more manual compactions."); | ||
| 2611 | 24 | return HA_EXIT_FAILURE; | |
| 2612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1207 times.
|
1207 | } else if (mc_id < 0) { |
| 2613 | ✗ | return HA_EXIT_FAILURE; | |
| 2614 | } | ||
| 2615 | |||
| 2616 | auto grd = | ||
| 2617 |
1/2✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
|
2414 | create_scope_guard([&]() { rdb_mc_thread.set_client_done(mc_id); }); |
| 2618 | // NO_LINT_DEBUG | ||
| 2619 |
9/18✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1207 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1207 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1207 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1207 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1207 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1207 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1207 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1207 times.
✗ Branch 17 not taken.
|
1207 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 2620 | "Manual compaction of column family: %s\n", cf); | ||
| 2621 | // Checking thd state every short cycle (100ms). This is for allowing to | ||
| 2622 | // exiting this function without waiting for CompactRange to finish. | ||
| 2623 | Rdb_manual_compaction_thread::Manual_compaction_request::mc_state | ||
| 2624 | mc_status; | ||
| 2625 | do { | ||
| 2626 |
1/2✓ Branch 0 taken 11565 times.
✗ Branch 1 not taken.
|
11566 | my_sleep(100000); |
| 2627 |
1/2✓ Branch 0 taken 11566 times.
✗ Branch 1 not taken.
|
11565 | mc_status = rdb_mc_thread.manual_compaction_state(mc_id); |
| 2628 |
6/6✓ Branch 0 taken 11554 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 4237 times.
✓ Branch 3 taken 7317 times.
✓ Branch 4 taken 10359 times.
✓ Branch 5 taken 1207 times.
|
15803 | } while (!thd->killed && |
| 2629 | (mc_status == Rdb_manual_compaction_thread:: | ||
| 2630 |
2/2✓ Branch 0 taken 3042 times.
✓ Branch 1 taken 1195 times.
|
4237 | Manual_compaction_request::PENDING || |
| 2631 | mc_status == Rdb_manual_compaction_thread:: | ||
| 2632 | Manual_compaction_request::RUNNING)); | ||
| 2633 | |||
| 2634 | 1207 | bool mc_timeout = false; | |
| 2635 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1195 times.
|
1207 | if (thd->killed) { |
| 2636 | // Cancelling pending or running manual compaction with 60s timeout | ||
| 2637 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | mc_timeout = rdb_mc_thread.cancel_manual_compaction_request(mc_id, 600); |
| 2638 | } | ||
| 2639 | |||
| 2640 |
1/2✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
|
1207 | mc_status = rdb_mc_thread.manual_compaction_state(mc_id); |
| 2641 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1189 times.
|
1207 | if (mc_status != |
| 2642 | Rdb_manual_compaction_thread::Manual_compaction_request::SUCCESS) { | ||
| 2643 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | std::string msg = "Manual Compaction Failed. Reason: "; |
| 2644 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
18 | if (thd->killed) { |
| 2645 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | msg += "Cancelled by client."; |
| 2646 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | } else if (mc_status == Rdb_manual_compaction_thread:: |
| 2647 | Manual_compaction_request::CANCEL) { | ||
| 2648 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | msg += "Cancelled by server."; |
| 2649 | } else { | ||
| 2650 | ✗ | msg += "General failures."; | |
| 2651 | } | ||
| 2652 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
|
18 | if (mc_timeout) { |
| 2653 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | msg += " (timeout)"; |
| 2654 | } | ||
| 2655 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | my_error(ER_INTERNAL_ERROR, MYF(0), msg.c_str()); |
| 2656 | 18 | return HA_EXIT_FAILURE; | |
| 2657 | 18 | } | |
| 2658 |
2/2✓ Branch 0 taken 1189 times.
✓ Branch 1 taken 18 times.
|
1207 | } |
| 2659 |
4/4✓ Branch 0 taken 1203 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 1203 times.
✓ Branch 3 taken 24 times.
|
1251 | } |
| 2660 | 1203 | return HA_EXIT_SUCCESS; | |
| 2661 | } | ||
| 2662 | |||
| 2663 | /* | ||
| 2664 | * Serializes an xid to a string so that it can | ||
| 2665 | * be used as a rocksdb transaction name | ||
| 2666 | */ | ||
| 2667 | 3613302 | static std::string rdb_xid_to_string(const XID &src) { | |
| 2668 |
3/4✓ Branch 0 taken 3613475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3613535 times.
✓ Branch 3 taken 21 times.
|
3613302 | assert(src.get_gtrid_length() >= 0 && |
| 2669 | src.get_gtrid_length() <= MAXGTRIDSIZE); | ||
| 2670 |
2/4✓ Branch 0 taken 3613687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3613923 times.
✗ Branch 3 not taken.
|
3613535 | assert(src.get_bqual_length() >= 0 && |
| 2671 | src.get_bqual_length() <= MAXBQUALSIZE); | ||
| 2672 | |||
| 2673 | 3613923 | std::string buf; | |
| 2674 |
1/2✓ Branch 0 taken 3613801 times.
✗ Branch 1 not taken.
|
3613562 | buf.reserve(RDB_XIDHDR_LEN + src.get_gtrid_length() + src.get_bqual_length()); |
| 2675 | |||
| 2676 | /* | ||
| 2677 | * expand formatID to fill 8 bytes if it doesn't already | ||
| 2678 | * then reinterpret bit pattern as unsigned and store in network order | ||
| 2679 | */ | ||
| 2680 | uchar fidbuf[RDB_FORMATID_SZ]; | ||
| 2681 | 3613801 | int64 signed_fid8 = src.get_format_id(); | |
| 2682 | 3613682 | const uint64 raw_fid8 = *reinterpret_cast<uint64 *>(&signed_fid8); | |
| 2683 | 3613682 | rdb_netbuf_store_uint64(fidbuf, raw_fid8); | |
| 2684 |
1/2✓ Branch 0 taken 3613492 times.
✗ Branch 1 not taken.
|
3613326 | buf.append(reinterpret_cast<const char *>(fidbuf), RDB_FORMATID_SZ); |
| 2685 | |||
| 2686 |
1/2✓ Branch 0 taken 3613454 times.
✗ Branch 1 not taken.
|
3613492 | buf.push_back(src.get_gtrid_length()); |
| 2687 |
1/2✓ Branch 0 taken 3613889 times.
✗ Branch 1 not taken.
|
3613454 | buf.push_back(src.get_bqual_length()); |
| 2688 |
1/2✓ Branch 0 taken 3613750 times.
✗ Branch 1 not taken.
|
3613489 | buf.append(src.get_data(), |
| 2689 | 3613889 | (src.get_gtrid_length()) + (src.get_bqual_length())); | |
| 2690 | 7227500 | return buf; | |
| 2691 | } | ||
| 2692 | |||
| 2693 | /////////////////////////////////////////////////////////////////////////////////////////// | ||
| 2694 | |||
| 2695 | /* | ||
| 2696 | Drop index thread's control | ||
| 2697 | */ | ||
| 2698 | |||
| 2699 | 25 | static void rocksdb_drop_index_wakeup_thread( | |
| 2700 | my_core::THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 2701 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 2702 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 2703 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 5 times.
|
25 | if (*static_cast<const bool *>(save)) { |
| 2704 | 20 | rdb_drop_idx_thread.signal(); | |
| 2705 | } | ||
| 2706 | 25 | } | |
| 2707 | |||
| 2708 | 12024589 | static inline uint32_t rocksdb_perf_context_level(THD *const thd) { | |
| 2709 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12024589 times.
|
12024589 | assert(thd != nullptr); |
| 2710 | |||
| 2711 | 12024589 | const int session_perf_context_level = THDVAR(thd, perf_context_level); | |
| 2712 |
2/2✓ Branch 0 taken 318 times.
✓ Branch 1 taken 12024424 times.
|
12024742 | if (session_perf_context_level > rocksdb::PerfLevel::kUninitialized) { |
| 2713 | 318 | return session_perf_context_level; | |
| 2714 | } | ||
| 2715 | |||
| 2716 | /* | ||
| 2717 | Fallback to global thdvar, if session specific one was not set to a valid | ||
| 2718 | value. | ||
| 2719 | */ | ||
| 2720 | |||
| 2721 | 12024424 | const int global_perf_context_level = THDVAR(nullptr, perf_context_level); | |
| 2722 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 12024490 times.
|
12024571 | if (global_perf_context_level > rocksdb::PerfLevel::kUninitialized) { |
| 2723 | 81 | return global_perf_context_level; | |
| 2724 | } | ||
| 2725 | |||
| 2726 | 12024490 | return rocksdb::PerfLevel::kDisable; | |
| 2727 | } | ||
| 2728 | |||
| 2729 | /* | ||
| 2730 | Very short (functor-like) interface to be passed to | ||
| 2731 | Rdb_transaction::walk_tx_list() | ||
| 2732 | */ | ||
| 2733 | |||
| 2734 | interface Rdb_tx_list_walker { | ||
| 2735 | 232 | virtual ~Rdb_tx_list_walker() {} | |
| 2736 | virtual void process_tran(const Rdb_transaction *const) = 0; | ||
| 2737 | }; | ||
| 2738 | |||
| 2739 | /* | ||
| 2740 | This is a helper class that is passed to RocksDB to get notifications when | ||
| 2741 | a snapshot gets created. | ||
| 2742 | */ | ||
| 2743 | |||
| 2744 | class Rdb_snapshot_notifier : public rocksdb::TransactionNotifier { | ||
| 2745 | Rdb_transaction *m_owning_tx; | ||
| 2746 | |||
| 2747 | void SnapshotCreated(const rocksdb::Snapshot *snapshot) override; | ||
| 2748 | |||
| 2749 | public: | ||
| 2750 | Rdb_snapshot_notifier(const Rdb_snapshot_notifier &) = delete; | ||
| 2751 | Rdb_snapshot_notifier &operator=(const Rdb_snapshot_notifier &) = delete; | ||
| 2752 | |||
| 2753 | 2567 | explicit Rdb_snapshot_notifier(Rdb_transaction *const owning_tx) | |
| 2754 | 2567 | : m_owning_tx(owning_tx) {} | |
| 2755 | |||
| 2756 | // If the owning Rdb_transaction gets destructed we need to not reference | ||
| 2757 | // it anymore. | ||
| 2758 | 2527 | void detach() { m_owning_tx = nullptr; } | |
| 2759 | }; | ||
| 2760 | |||
| 2761 | /* This is the base class for transactions when interacting with rocksdb. | ||
| 2762 | */ | ||
| 2763 | class Rdb_transaction { | ||
| 2764 | protected: | ||
| 2765 | ulonglong m_write_count = 0; | ||
| 2766 | // per row data | ||
| 2767 | ulonglong m_row_lock_count = 0; | ||
| 2768 | std::unordered_map<GL_INDEX_ID, ulonglong> m_auto_incr_map; | ||
| 2769 | |||
| 2770 | bool m_is_delayed_snapshot = false; | ||
| 2771 | |||
| 2772 | std::unordered_set<Rdb_tbl_def *> modified_tables; | ||
| 2773 | |||
| 2774 | private: | ||
| 2775 | /* | ||
| 2776 | Number of write operations this transaction had when we took the last | ||
| 2777 | savepoint (the idea is not to take another savepoint if we haven't made | ||
| 2778 | any changes) | ||
| 2779 | */ | ||
| 2780 | ulonglong m_writes_at_last_savepoint; | ||
| 2781 | |||
| 2782 | protected: | ||
| 2783 | THD *m_thd = nullptr; | ||
| 2784 | |||
| 2785 | static std::multiset<Rdb_transaction *> s_tx_list; | ||
| 2786 | static Rds_mysql_mutex s_tx_list_mutex; | ||
| 2787 | |||
| 2788 | Rdb_io_perf *m_tbl_io_perf; | ||
| 2789 | |||
| 2790 | bool m_tx_read_only = false; | ||
| 2791 | |||
| 2792 | int m_timeout_sec; /* Cached value of @@rocksdb_lock_wait_timeout */ | ||
| 2793 | |||
| 2794 | /* Maximum number of locks the transaction can have */ | ||
| 2795 | ulonglong m_max_row_locks; | ||
| 2796 | |||
| 2797 | bool m_is_tx_failed = false; | ||
| 2798 | bool m_rollback_only = false; | ||
| 2799 | |||
| 2800 | std::shared_ptr<Rdb_snapshot_notifier> m_notifier; | ||
| 2801 | |||
| 2802 | // This should be used only when updating binlog information. | ||
| 2803 | virtual rocksdb::WriteBatchBase *get_write_batch() = 0; | ||
| 2804 | virtual bool commit_no_binlog() = 0; | ||
| 2805 | virtual rocksdb::Iterator *get_iterator( | ||
| 2806 | const rocksdb::ReadOptions &options, | ||
| 2807 | rocksdb::ColumnFamilyHandle *column_family) = 0; | ||
| 2808 | |||
| 2809 | /* | ||
| 2810 | @detail | ||
| 2811 | This function takes in the WriteBatch of the transaction to add | ||
| 2812 | all the AUTO_INCREMENT merges. It does so by iterating through | ||
| 2813 | m_auto_incr_map and then constructing key/value pairs to call merge upon. | ||
| 2814 | |||
| 2815 | @param wb | ||
| 2816 | */ | ||
| 2817 | 6865664 | rocksdb::Status merge_auto_incr_map(rocksdb::WriteBatchBase *const wb) { | |
| 2818 |
3/4✓ Branch 0 taken 6865754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 6865730 times.
|
6865664 | DBUG_EXECUTE_IF("myrocks_autoinc_upgrade", return rocksdb::Status::OK();); |
| 2819 | |||
| 2820 | // Iterate through the merge map merging all keys into data dictionary. | ||
| 2821 | 6865730 | rocksdb::Status s; | |
| 2822 |
2/2✓ Branch 0 taken 132812 times.
✓ Branch 1 taken 6865846 times.
|
6998817 | for (auto &it : m_auto_incr_map) { |
| 2823 | 132846 | s = dict_manager.get_dict_manager_selector_const(it.first.cf_id) | |
| 2824 |
2/4✓ Branch 0 taken 132812 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132838 times.
✗ Branch 3 not taken.
|
132846 | ->put_auto_incr_val(wb, it.first, it.second); |
| 2825 |
2/4✓ Branch 0 taken 133000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133000 times.
|
132995 | if (!s.ok()) { |
| 2826 | ✗ | return s; | |
| 2827 | } | ||
| 2828 | } | ||
| 2829 | 6865846 | m_auto_incr_map.clear(); | |
| 2830 | 6865717 | return s; | |
| 2831 | 6865886 | } | |
| 2832 | |||
| 2833 | protected: | ||
| 2834 | /* | ||
| 2835 | The following two are helper functions to be overloaded by child classes. | ||
| 2836 | They should provide RocksDB's savepoint semantics. | ||
| 2837 | */ | ||
| 2838 | virtual void do_set_savepoint() = 0; | ||
| 2839 | virtual rocksdb::Status do_pop_savepoint() = 0; | ||
| 2840 | virtual void do_rollback_to_savepoint() = 0; | ||
| 2841 | |||
| 2842 | public: | ||
| 2843 | rocksdb::ReadOptions m_read_opts; | ||
| 2844 | int64_t m_snapshot_timestamp = 0; | ||
| 2845 | bool m_ddl_transaction; | ||
| 2846 | |||
| 2847 | /* | ||
| 2848 | Tracks the number of tables in use through external_lock. | ||
| 2849 | This should not be reset during start_tx(). | ||
| 2850 | */ | ||
| 2851 | int64_t m_n_mysql_tables_in_use = 0; | ||
| 2852 | |||
| 2853 | /* | ||
| 2854 | for distinction between rdb_transaction_impl and rdb_writebatch_impl | ||
| 2855 | when using walk tx list | ||
| 2856 | */ | ||
| 2857 | virtual bool is_writebatch_trx() const = 0; | ||
| 2858 | |||
| 2859 | 932 | static void init_mutex() { | |
| 2860 | 932 | s_tx_list_mutex.init(key_mutex_tx_list, MY_MUTEX_INIT_FAST); | |
| 2861 | 932 | } | |
| 2862 | |||
| 2863 | 899 | static void term_mutex() { | |
| 2864 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 899 times.
|
899 | assert(s_tx_list.size() == 0); |
| 2865 | 899 | s_tx_list_mutex.destroy(); | |
| 2866 | 899 | } | |
| 2867 | |||
| 2868 | 116 | static void walk_tx_list(Rdb_tx_list_walker *walker) { | |
| 2869 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
|
116 | assert(walker != nullptr); |
| 2870 | |||
| 2871 | 116 | RDB_MUTEX_LOCK_CHECK(s_tx_list_mutex); | |
| 2872 | |||
| 2873 |
3/4✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
✓ Branch 3 taken 116 times.
|
455 | for (auto it : s_tx_list) walker->process_tran(it); |
| 2874 | |||
| 2875 | 116 | RDB_MUTEX_UNLOCK_CHECK(s_tx_list_mutex); | |
| 2876 | 116 | } | |
| 2877 | |||
| 2878 | 439 | int set_status_error(THD *const thd, const rocksdb::Status &s, | |
| 2879 | const Rdb_key_def &kd, | ||
| 2880 | const Rdb_tbl_def *const tbl_def) { | ||
| 2881 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
|
439 | assert(!s.ok()); |
| 2882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
|
439 | assert(tbl_def != nullptr); |
| 2883 | |||
| 2884 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 143 times.
|
439 | if (s.IsTimedOut()) { |
| 2885 | /* | ||
| 2886 | SQL layer has weird expectations. If we return an error when | ||
| 2887 | doing a read in DELETE IGNORE, it will ignore the error ("because it's | ||
| 2888 | an IGNORE command!) but then will fail an assert, because "error code | ||
| 2889 | was returned, but no error happened". Do what InnoDB's | ||
| 2890 | convert_error_code_to_mysql() does: force a statement | ||
| 2891 | rollback before returning HA_ERR_LOCK_WAIT_TIMEOUT: | ||
| 2892 | */ | ||
| 2893 | 296 | thd->mark_transaction_to_rollback( | |
| 2894 | static_cast<bool>(rocksdb_rollback_on_timeout)); | ||
| 2895 | |||
| 2896 | 296 | rocksdb_row_lock_wait_timeouts++; | |
| 2897 | |||
| 2898 | 296 | return HA_ERR_LOCK_WAIT_TIMEOUT; | |
| 2899 | } | ||
| 2900 | |||
| 2901 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 104 times.
|
143 | if (s.IsDeadlock()) { |
| 2902 | 39 | thd->mark_transaction_to_rollback(true /* whole transaction */); | |
| 2903 | 39 | rocksdb_row_lock_deadlocks++; | |
| 2904 | 39 | return HA_ERR_LOCK_DEADLOCK; | |
| 2905 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 19 times.
|
104 | } else if (s.IsBusy()) { |
| 2906 | 85 | rocksdb_snapshot_conflict_errors++; | |
| 2907 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 82 times.
|
85 | if (rocksdb_print_snapshot_conflict_queries) { |
| 2908 | char user_host_buff[MAX_USER_HOST_SIZE + 1]; | ||
| 2909 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | make_user_name(thd->security_context(), user_host_buff); |
| 2910 |
11/22✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 3 times.
✗ Branch 21 not taken.
|
3 | LogPluginErrMsg(WARNING_LEVEL, 0, |
| 2911 | "Got snapshot conflict errors: User: %s Query: %.*s", | ||
| 2912 | user_host_buff, static_cast<int>(thd->query().length), | ||
| 2913 | thd->query().str); | ||
| 2914 | } | ||
| 2915 | 85 | return HA_ERR_ROCKSDB_STATUS_BUSY; | |
| 2916 | } | ||
| 2917 | |||
| 2918 |
3/6✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
|
19 | if (s.IsIOError() || s.IsCorruption()) { |
| 2919 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_GENERAL); | |
| 2920 | } | ||
| 2921 | |||
| 2922 | 19 | return ha_rocksdb::rdb_error_to_mysql(s); | |
| 2923 | } | ||
| 2924 | |||
| 2925 | 13045834 | THD *get_thd() const { return m_thd; } | |
| 2926 | |||
| 2927 | /* Used for tracking io_perf counters */ | ||
| 2928 | 7992195 | void io_perf_start(Rdb_io_perf *const io_perf) { | |
| 2929 | /* | ||
| 2930 | Since perf_context is tracked per thread, it is difficult and expensive | ||
| 2931 | to maintain perf_context on a per table basis. Therefore, roll all | ||
| 2932 | perf_context data into the first table used in a query. This works well | ||
| 2933 | for single table queries and is probably good enough for queries that hit | ||
| 2934 | multiple tables. | ||
| 2935 | |||
| 2936 | perf_context stats gathering is started when the table lock is acquired | ||
| 2937 | or when ha_rocksdb::start_stmt is called in case of LOCK TABLES. They | ||
| 2938 | are recorded when the table lock is released, or when commit/rollback | ||
| 2939 | is called on the transaction, whichever comes first. Table lock release | ||
| 2940 | and commit/rollback can happen in different orders. In the case where | ||
| 2941 | the lock is released before commit/rollback is called, an extra step to | ||
| 2942 | gather stats during commit/rollback is needed. | ||
| 2943 | */ | ||
| 2944 |
4/4✓ Branch 0 taken 7992189 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 141 times.
✓ Branch 3 taken 7992362 times.
|
15984692 | if (m_tbl_io_perf == nullptr && |
| 2945 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 7992356 times.
|
7992189 | io_perf->start(rocksdb_perf_context_level(m_thd))) { |
| 2946 | 141 | m_tbl_io_perf = io_perf; | |
| 2947 | } | ||
| 2948 | 7992503 | } | |
| 2949 | |||
| 2950 | 4008373 | void io_perf_end_and_record(void) { | |
| 2951 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 4008232 times.
|
4008373 | if (m_tbl_io_perf != nullptr) { |
| 2952 | 141 | m_tbl_io_perf->end_and_record(rocksdb_perf_context_level(m_thd)); | |
| 2953 | 141 | m_tbl_io_perf = nullptr; | |
| 2954 | } | ||
| 2955 | 4008373 | } | |
| 2956 | |||
| 2957 | 3983749 | void io_perf_end_and_record(Rdb_io_perf *const io_perf) { | |
| 2958 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 3983707 times.
|
3983749 | if (m_tbl_io_perf == io_perf) { |
| 2959 | 42 | io_perf_end_and_record(); | |
| 2960 | } | ||
| 2961 | 3983749 | } | |
| 2962 | |||
| 2963 | 112300888 | void set_params(int timeout_sec_arg, int max_row_locks_arg) { | |
| 2964 | 112300888 | m_timeout_sec = timeout_sec_arg; | |
| 2965 | 112300888 | m_max_row_locks = max_row_locks_arg; | |
| 2966 | 112300888 | set_lock_timeout(timeout_sec_arg); | |
| 2967 | 112299898 | } | |
| 2968 | |||
| 2969 | virtual void set_lock_timeout(int timeout_sec_arg) = 0; | ||
| 2970 | |||
| 2971 | 49587101 | ulonglong get_write_count() const { return m_write_count; } | |
| 2972 | |||
| 2973 | 12600560 | ulonglong get_row_lock_count() const { return m_row_lock_count; } | |
| 2974 | |||
| 2975 | 12617910 | void incr_row_lock_count() { ++m_row_lock_count; } | |
| 2976 | |||
| 2977 | 12622908 | ulonglong get_max_row_lock_count() const { return m_max_row_locks; } | |
| 2978 | |||
| 2979 | 161 | int get_timeout_sec() const { return m_timeout_sec; } | |
| 2980 | |||
| 2981 | virtual void set_sync(bool sync) = 0; | ||
| 2982 | |||
| 2983 | virtual void release_lock(const Rdb_key_def &key_descr, | ||
| 2984 | const std::string &rowkey, bool force = false) = 0; | ||
| 2985 | |||
| 2986 | virtual bool prepare() = 0; | ||
| 2987 | |||
| 2988 | 3554159 | bool commit_or_rollback() { | |
| 2989 | bool res; | ||
| 2990 |
2/2✓ Branch 0 taken 43915 times.
✓ Branch 1 taken 3510244 times.
|
3554159 | if (m_is_tx_failed) { |
| 2991 | 43915 | rollback(); | |
| 2992 | 43915 | res = false; | |
| 2993 | } else { | ||
| 2994 | 3510244 | res = commit(); | |
| 2995 | } | ||
| 2996 | 3554073 | return res; | |
| 2997 | } | ||
| 2998 | |||
| 2999 | 7093760 | bool commit() { | |
| 3000 |
2/2✓ Branch 0 taken 3661984 times.
✓ Branch 1 taken 3431855 times.
|
7093760 | if (get_write_count() == 0) { |
| 3001 | 3661984 | rollback(); | |
| 3002 | 3661828 | return false; | |
| 3003 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3431852 times.
|
3431855 | } else if (m_rollback_only) { |
| 3004 | /* | ||
| 3005 | Transactions marked as rollback_only are expected to be rolled back at | ||
| 3006 | prepare(). But there are some exceptions like below that prepare() is | ||
| 3007 | never called and commit() is called instead. | ||
| 3008 | 1. Binlog is disabled | ||
| 3009 | 2. No modification exists in binlog cache for the transaction (#195) | ||
| 3010 | In both cases, rolling back transaction is safe. Nothing is written to | ||
| 3011 | binlog. | ||
| 3012 | */ | ||
| 3013 | 3 | my_error(ER_ROLLBACK_ONLY, MYF(0)); | |
| 3014 | 3 | rollback(); | |
| 3015 | 3 | return true; | |
| 3016 | } else { | ||
| 3017 | 3431852 | return commit_no_binlog(); | |
| 3018 | } | ||
| 3019 | } | ||
| 3020 | |||
| 3021 | virtual void rollback() = 0; | ||
| 3022 | |||
| 3023 | 3558276 | void snapshot_created(const rocksdb::Snapshot *const snapshot) { | |
| 3024 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3558276 times.
|
3558276 | assert(snapshot != nullptr); |
| 3025 | |||
| 3026 | 3558276 | m_read_opts.snapshot = snapshot; | |
| 3027 | // TODO: Use snapshot timestamp from rocksdb Snapshot object itself. This | ||
| 3028 | // saves the extra call to fetch current time, and allows TTL compaction | ||
| 3029 | // (which uses rocksdb timestamp) to be consistent with TTL read filtering | ||
| 3030 | // (which uses this timestamp). | ||
| 3031 | // | ||
| 3032 | // There is no correctness problem though since m_snapshot_timestamp is | ||
| 3033 | // generally set after the snapshot has been created, so compaction is | ||
| 3034 | // not dropping anything that should have been visible. | ||
| 3035 | 3558276 | rdb->GetEnv()->GetCurrentTime(&m_snapshot_timestamp); | |
| 3036 | 3558382 | m_is_delayed_snapshot = false; | |
| 3037 | 3558382 | } | |
| 3038 | |||
| 3039 | virtual void acquire_snapshot(bool acquire_now) = 0; | ||
| 3040 | virtual void release_snapshot() = 0; | ||
| 3041 | |||
| 3042 | 269465 | bool has_snapshot() const { return m_read_opts.snapshot != nullptr; } | |
| 3043 | |||
| 3044 | private: | ||
| 3045 | // The Rdb_sst_info structures we are currently loading. In a partitioned | ||
| 3046 | // table this can have more than one entry | ||
| 3047 | std::vector<std::shared_ptr<Rdb_sst_info>> m_curr_bulk_load; | ||
| 3048 | std::string m_curr_bulk_load_tablename; | ||
| 3049 | |||
| 3050 | /* External merge sorts for bulk load: key ID -> merge sort instance */ | ||
| 3051 | std::unordered_map<GL_INDEX_ID, Rdb_index_merge> m_key_merge; | ||
| 3052 | |||
| 3053 | /* | ||
| 3054 | Used to check for duplicate entries during fast unique secondary index | ||
| 3055 | creation. | ||
| 3056 | */ | ||
| 3057 | struct unique_sk_buf_info { | ||
| 3058 | bool sk_buf_switch = false; | ||
| 3059 | rocksdb::Slice sk_memcmp_key; | ||
| 3060 | rocksdb::Slice sk_memcmp_key_old; | ||
| 3061 | uchar *dup_sk_buf = nullptr; | ||
| 3062 | uchar *dup_sk_buf_old = nullptr; | ||
| 3063 | |||
| 3064 | /* | ||
| 3065 | This method is meant to be called back to back during inplace creation | ||
| 3066 | of unique indexes. It will switch between two buffers, which | ||
| 3067 | will each store the memcmp form of secondary keys, which are then | ||
| 3068 | converted to slices in sk_memcmp_key or sk_memcmp_key_old. | ||
| 3069 | |||
| 3070 | Switching buffers on each iteration allows us to retain the | ||
| 3071 | sk_memcmp_key_old value for duplicate comparison. | ||
| 3072 | */ | ||
| 3073 | 66 | inline uchar *swap_and_get_sk_buf() { | |
| 3074 | 66 | sk_buf_switch = !sk_buf_switch; | |
| 3075 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 27 times.
|
66 | return sk_buf_switch ? dup_sk_buf : dup_sk_buf_old; |
| 3076 | } | ||
| 3077 | |||
| 3078 | 445 | ~unique_sk_buf_info() { | |
| 3079 | 445 | my_free(dup_sk_buf); | |
| 3080 | 445 | dup_sk_buf = nullptr; | |
| 3081 | 445 | my_free(dup_sk_buf_old); | |
| 3082 | 445 | dup_sk_buf_old = nullptr; | |
| 3083 | 445 | } | |
| 3084 | }; | ||
| 3085 | |||
| 3086 | public: | ||
| 3087 | 24080865 | int get_key_merge(GL_INDEX_ID kd_gl_id, rocksdb::ColumnFamilyHandle *cf, | |
| 3088 | Rdb_index_merge **key_merge) { | ||
| 3089 | int res; | ||
| 3090 |
1/2✓ Branch 0 taken 24080865 times.
✗ Branch 1 not taken.
|
24080865 | auto it = m_key_merge.find(kd_gl_id); |
| 3091 |
2/2✓ Branch 0 taken 475 times.
✓ Branch 1 taken 24080390 times.
|
24080865 | if (it == m_key_merge.end()) { |
| 3092 |
1/2✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
|
475 | m_key_merge.emplace( |
| 3093 |
1/2✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
|
475 | std::piecewise_construct, std::make_tuple(kd_gl_id), |
| 3094 | ✗ | std::make_tuple( | |
| 3095 |
3/6✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 475 times.
✗ Branch 5 not taken.
|
475 | get_rocksdb_tmpdir(), THDVAR(get_thd(), merge_buf_size), |
| 3096 |
1/2✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
|
475 | THDVAR(get_thd(), merge_combine_read_size), |
| 3097 |
1/2✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
|
475 | THDVAR(get_thd(), merge_tmp_file_removal_delay_ms), cf)); |
| 3098 |
1/2✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
|
475 | it = m_key_merge.find(kd_gl_id); |
| 3099 |
2/4✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 475 times.
|
475 | if ((res = it->second.init()) != 0) { |
| 3100 | ✗ | return res; | |
| 3101 | } | ||
| 3102 | } | ||
| 3103 | 24080865 | *key_merge = &it->second; | |
| 3104 | 24080865 | return HA_EXIT_SUCCESS; | |
| 3105 | } | ||
| 3106 | |||
| 3107 | /* Finish bulk loading for all table handlers belongs to one connection */ | ||
| 3108 | 3243 | int finish_bulk_load(bool *is_critical_error = nullptr, | |
| 3109 | bool print_client_error = true, | ||
| 3110 | TABLE *table_arg = nullptr, | ||
| 3111 | char *table_name_arg = nullptr) { | ||
| 3112 |
2/2✓ Branch 0 taken 2716 times.
✓ Branch 1 taken 528 times.
|
3243 | if (m_curr_bulk_load.size() == 0) { |
| 3113 |
1/2✓ Branch 0 taken 2716 times.
✗ Branch 1 not taken.
|
2716 | if (is_critical_error) { |
| 3114 | 2716 | *is_critical_error = false; | |
| 3115 | } | ||
| 3116 | 2716 | return HA_EXIT_SUCCESS; | |
| 3117 | } | ||
| 3118 | |||
| 3119 |
2/4✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 529 times.
|
528 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3120 | // NO_LINT_DEBUG | ||
| 3121 | ✗ | LogPluginErrMsg( | |
| 3122 | INFORMATION_LEVEL, 0, | ||
| 3123 | "SST Tracing : Finishing bulk loading operation for table '%s'", | ||
| 3124 | m_curr_bulk_load_tablename.c_str()); | ||
| 3125 | } | ||
| 3126 | |||
| 3127 | 529 | Ensure_cleanup cleanup([&]() { | |
| 3128 | // Always clear everything regardless of success/failure | ||
| 3129 | 529 | m_curr_bulk_load.clear(); | |
| 3130 | 529 | m_curr_bulk_load_tablename.clear(); | |
| 3131 | 529 | m_key_merge.clear(); | |
| 3132 |
1/2✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
|
529 | }); |
| 3133 | |||
| 3134 | 529 | int rc = 0; | |
| 3135 |
2/2✓ Branch 0 taken 472 times.
✓ Branch 1 taken 57 times.
|
529 | if (is_critical_error) { |
| 3136 | 472 | *is_critical_error = true; | |
| 3137 | } | ||
| 3138 | |||
| 3139 | // PREPARE phase: finish all on-going bulk loading Rdb_sst_info and | ||
| 3140 | // collect all Rdb_sst_commit_info containing (SST files, cf) | ||
| 3141 |
2/4✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 529 times.
|
529 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3142 | // NO_LINT_DEBUG | ||
| 3143 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 3144 | "SST Tracing : Finishing '%zu' active SST files", | ||
| 3145 | m_curr_bulk_load.size()); | ||
| 3146 | } | ||
| 3147 | |||
| 3148 | 529 | int rc2 = 0; | |
| 3149 | 529 | std::vector<Rdb_sst_info::Rdb_sst_commit_info> sst_commit_list; | |
| 3150 |
1/2✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
|
529 | sst_commit_list.reserve(m_curr_bulk_load.size()); |
| 3151 | |||
| 3152 |
2/2✓ Branch 0 taken 586 times.
✓ Branch 1 taken 529 times.
|
1115 | for (auto &sst_info : m_curr_bulk_load) { |
| 3153 | 586 | Rdb_sst_info::Rdb_sst_commit_info commit_info; | |
| 3154 | |||
| 3155 | // Commit the list of SST files and move it to the end of | ||
| 3156 | // sst_commit_list, effectively transfer the ownership over | ||
| 3157 |
1/2✓ Branch 0 taken 586 times.
✗ Branch 1 not taken.
|
586 | rc2 = sst_info->finish(&commit_info, print_client_error); |
| 3158 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 586 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
586 | if (rc2 && rc == 0) { |
| 3159 | // Don't return yet - make sure we finish all the SST infos | ||
| 3160 | ✗ | rc = rc2; | |
| 3161 | } | ||
| 3162 | |||
| 3163 | // Make sure we have work to do - we might be losing the race | ||
| 3164 |
5/6✓ Branch 0 taken 586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
✓ Branch 3 taken 443 times.
✓ Branch 4 taken 143 times.
✓ Branch 5 taken 443 times.
|
586 | if (rc2 == 0 && commit_info.has_work()) { |
| 3165 |
1/2✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
|
143 | sst_commit_list.emplace_back(std::move(commit_info)); |
| 3166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 143 times.
|
143 | assert(!commit_info.has_work()); |
| 3167 | } | ||
| 3168 | 586 | } | |
| 3169 | |||
| 3170 |
2/4✓ Branch 0 taken 529 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 529 times.
|
529 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3171 | // NO_LINT_DEBUG | ||
| 3172 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 3173 | "SST Tracing : All active SST files finished"); | ||
| 3174 | } | ||
| 3175 | |||
| 3176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 529 times.
|
529 | if (rc) { |
| 3177 | ✗ | return rc; | |
| 3178 | } | ||
| 3179 | |||
| 3180 | // MERGING Phase: Flush the index_merge sort buffers into SST files in | ||
| 3181 | // Rdb_sst_info and collect all Rdb_sst_commit_info containing | ||
| 3182 | // (SST files, cf) | ||
| 3183 |
2/2✓ Branch 0 taken 433 times.
✓ Branch 1 taken 96 times.
|
529 | if (!m_key_merge.empty()) { |
| 3184 |
2/4✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 433 times.
|
433 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3185 | // NO_LINT_DEBUG | ||
| 3186 | ✗ | LogPluginErrMsg( | |
| 3187 | INFORMATION_LEVEL, 0, | ||
| 3188 | "SST Tracing : Started flushing index_merge sort buffer"); | ||
| 3189 | } | ||
| 3190 | |||
| 3191 | 433 | Ensure_cleanup malloc_cleanup([]() { | |
| 3192 | /* | ||
| 3193 | Explicitly tell jemalloc to clean up any unused dirty pages at this | ||
| 3194 | point. | ||
| 3195 | See https://reviews.facebook.net/D63723 for more details. | ||
| 3196 | */ | ||
| 3197 | 433 | purge_all_jemalloc_arenas(); | |
| 3198 |
1/2✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
|
433 | }); |
| 3199 | |||
| 3200 | 433 | rocksdb::Slice merge_key; | |
| 3201 | 433 | rocksdb::Slice merge_val; | |
| 3202 |
2/2✓ Branch 0 taken 475 times.
✓ Branch 1 taken 412 times.
|
887 | for (auto it = m_key_merge.begin(); it != m_key_merge.end(); it++) { |
| 3203 | 475 | GL_INDEX_ID index_id = it->first; | |
| 3204 | std::shared_ptr<const Rdb_key_def> keydef = | ||
| 3205 |
1/2✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
|
475 | ddl_manager.safe_find(index_id); |
| 3206 | 475 | std::string table_name; | |
| 3207 |
2/2✓ Branch 0 taken 358 times.
✓ Branch 1 taken 117 times.
|
475 | if (table_name_arg) { |
| 3208 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | table_name = table_name_arg; |
| 3209 | } else { | ||
| 3210 |
2/4✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
✗ Branch 3 not taken.
|
117 | table_name = ddl_manager.safe_get_table_name(index_id); |
| 3211 | // Rdb_sst_info expects a denormalized table name in the form of | ||
| 3212 | // "./database/table" | ||
| 3213 | 117 | std::replace(table_name.begin(), table_name.end(), '.', '/'); | |
| 3214 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | table_name = "./" + table_name; |
| 3215 | } | ||
| 3216 | |||
| 3217 | // Unable to find key definition or table name since the | ||
| 3218 | // table could have been dropped. | ||
| 3219 | // TODO(herman): there is a race here between dropping the table | ||
| 3220 | // and detecting a drop here. If the table is dropped while bulk | ||
| 3221 | // loading is finishing, these keys being added here may | ||
| 3222 | // be missed by the compaction filter and not be marked for | ||
| 3223 | // removal. It is unclear how to lock the sql table from the storage | ||
| 3224 | // engine to prevent modifications to it while bulk load is occurring. | ||
| 3225 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 469 times.
|
475 | if (keydef == nullptr) { |
| 3226 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (is_critical_error) { |
| 3227 | // We used to set the error but simply ignores it. This follows | ||
| 3228 | // current behavior and we should revisit this later | ||
| 3229 | 6 | *is_critical_error = false; | |
| 3230 | } | ||
| 3231 | 6 | return HA_ERR_KEY_NOT_FOUND; | |
| 3232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
|
469 | } else if (table_name.empty()) { |
| 3233 | ✗ | if (is_critical_error) { | |
| 3234 | // We used to set the error but simply ignores it. This follows | ||
| 3235 | // current behavior and we should revisit this later | ||
| 3236 | ✗ | *is_critical_error = false; | |
| 3237 | } | ||
| 3238 | ✗ | return HA_ERR_NO_SUCH_TABLE; | |
| 3239 | } | ||
| 3240 | |||
| 3241 | // Currently, unique indexes only checked in the inplace alter path, | ||
| 3242 | // but not in allow_sk bulk load path. | ||
| 3243 | bool is_unique_index = | ||
| 3244 |
2/2✓ Branch 0 taken 355 times.
✓ Branch 1 taken 114 times.
|
824 | table_arg && |
| 3245 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 328 times.
|
355 | table_arg->key_info[keydef->get_keyno()].flags & HA_NOSAME; |
| 3246 | |||
| 3247 | 469 | const std::string &index_name = keydef->get_name(); | |
| 3248 | |||
| 3249 |
2/4✓ Branch 0 taken 469 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 469 times.
|
469 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3250 | ✗ | std::string full_name; | |
| 3251 | ✗ | int err = rdb_normalize_tablename(table_name, &full_name); | |
| 3252 | ✗ | if (err != HA_EXIT_SUCCESS) { | |
| 3253 | ✗ | full_name = table_name; | |
| 3254 | } | ||
| 3255 | |||
| 3256 | // NO_LINT_DEBUG | ||
| 3257 | ✗ | LogPluginErrMsg( | |
| 3258 | INFORMATION_LEVEL, 0, | ||
| 3259 | "SST Tracing : Flushing index_merge sort buffer for table '%s' " | ||
| 3260 | "and index '%s'", | ||
| 3261 | full_name.c_str(), index_name.c_str()); | ||
| 3262 | } | ||
| 3263 | |||
| 3264 | 469 | Rdb_index_merge &rdb_merge = it->second; | |
| 3265 | |||
| 3266 | auto sst_info = std::make_shared<Rdb_sst_info>( | ||
| 3267 | 469 | rdb, table_name, index_name, rdb_merge.get_cf(), | |
| 3268 |
2/4✓ Branch 0 taken 469 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 469 times.
✗ Branch 3 not taken.
|
938 | *rocksdb_db_options, THDVAR(get_thd(), trace_sst_api)); |
| 3269 | |||
| 3270 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 445 times.
|
469 | if (keydef->is_partial_index()) { |
| 3271 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
|
24 | if (!THDVAR(m_thd, bulk_load_partial_index)) continue; |
| 3272 | // For partial indexes, we only want to materialize groups that reach | ||
| 3273 | // the materialization threshold. The idea is to buffer the rows up to | ||
| 3274 | // the threshold, and only actually insert the keys once we break the | ||
| 3275 | // threshold. | ||
| 3276 | 24 | bool materialized = false; | |
| 3277 | 24 | rocksdb::Slice cur_prefix; | |
| 3278 | 24 | std::vector<std::pair<rocksdb::Slice, rocksdb::Slice>> keys; | |
| 3279 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | MEM_ROOT mem_root; |
| 3280 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | init_sql_alloc(PSI_NOT_INSTRUMENTED, &mem_root, 4024); |
| 3281 | |||
| 3282 |
3/4✓ Branch 0 taken 1344 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1320 times.
✓ Branch 3 taken 24 times.
|
1344 | while ((rc2 = rdb_merge.next(&merge_key, &merge_val)) == 0) { |
| 3283 |
4/4✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 240 times.
✓ Branch 3 taken 1080 times.
|
2616 | if (cur_prefix.size() == 0 || |
| 3284 |
3/4✓ Branch 0 taken 1296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
✓ Branch 3 taken 1080 times.
|
1296 | !keydef->value_matches_prefix(merge_key, cur_prefix)) { |
| 3285 |
6/6✓ Branch 0 taken 60 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 210 times.
|
240 | if (keydef->m_is_reverse_cf && materialized) { |
| 3286 | // Write sentinel before moving to next prefix. | ||
| 3287 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | rc2 = sst_info->put(cur_prefix, rocksdb::Slice()); |
| 3288 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | if (rc2 != 0) { |
| 3289 | ✗ | break; | |
| 3290 | } | ||
| 3291 | } | ||
| 3292 | |||
| 3293 | // This is a new group, so clear any rows buffered from a prior | ||
| 3294 | // group. | ||
| 3295 |
1/2✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
|
240 | mem_root.ClearForReuse(); |
| 3296 | 240 | keys.clear(); | |
| 3297 | 240 | materialized = false; | |
| 3298 | |||
| 3299 | // Determine the length of the new group prefix | ||
| 3300 | 240 | Rdb_string_reader reader(&merge_key); | |
| 3301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
|
240 | if ((!reader.read(Rdb_key_def::INDEX_NUMBER_SIZE))) { |
| 3302 | ✗ | rc2 = HA_ERR_ROCKSDB_CORRUPT_DATA; | |
| 3303 | ✗ | break; | |
| 3304 | } | ||
| 3305 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 240 times.
|
480 | for (uint i = 0; i < keydef->partial_index_keyparts(); i++) { |
| 3306 |
2/4✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 240 times.
|
240 | if (keydef->read_memcmp_key_part(&reader, i) > 0) { |
| 3307 | ✗ | rc2 = HA_ERR_ROCKSDB_CORRUPT_DATA; | |
| 3308 | ✗ | break; | |
| 3309 | } | ||
| 3310 | } | ||
| 3311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
|
240 | if (rc2) break; |
| 3312 | |||
| 3313 | size_t cur_prefix_len = | ||
| 3314 | 240 | reader.get_current_ptr() - merge_key.data(); | |
| 3315 | |||
| 3316 |
1/2✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
|
240 | const char *key = (const char *)memdup_root( |
| 3317 | 240 | &mem_root, merge_key.data(), cur_prefix_len); | |
| 3318 | |||
| 3319 | // Set the current prefix. | ||
| 3320 | 240 | cur_prefix = rocksdb::Slice(key, cur_prefix_len); | |
| 3321 | } | ||
| 3322 | |||
| 3323 |
2/2✓ Branch 0 taken 1080 times.
✓ Branch 1 taken 240 times.
|
1320 | if (!materialized) { |
| 3324 | // Bulk load the keys if threshold is exceeded. | ||
| 3325 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 960 times.
|
1080 | if (keys.size() >= keydef->partial_index_threshold()) { |
| 3326 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 30 times.
|
120 | if (!keydef->m_is_reverse_cf) { |
| 3327 | // Write sentinel | ||
| 3328 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | rc2 = sst_info->put(cur_prefix, rocksdb::Slice()); |
| 3329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (rc2 != 0) { |
| 3330 | ✗ | break; | |
| 3331 | } | ||
| 3332 | } | ||
| 3333 | |||
| 3334 |
2/2✓ Branch 0 taken 600 times.
✓ Branch 1 taken 120 times.
|
720 | for (const auto &k : keys) { |
| 3335 |
2/4✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
|
600 | if ((rc2 = sst_info->put(k.first, k.second) != 0)) { |
| 3336 | ✗ | break; | |
| 3337 | } | ||
| 3338 | } | ||
| 3339 | |||
| 3340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
|
120 | if (rc2 != 0) { |
| 3341 | ✗ | break; | |
| 3342 | } | ||
| 3343 | |||
| 3344 | 120 | materialized = true; | |
| 3345 | 120 | keys.clear(); | |
| 3346 | } else { | ||
| 3347 | // Threshold not exceeded, just buffer the row in the keys | ||
| 3348 | // vector. | ||
| 3349 |
1/2✓ Branch 0 taken 960 times.
✗ Branch 1 not taken.
|
1920 | const char *key = (const char *)memdup_root( |
| 3350 | 960 | &mem_root, merge_key.data(), merge_key.size()); | |
| 3351 |
1/2✓ Branch 0 taken 960 times.
✗ Branch 1 not taken.
|
1920 | const char *val = (const char *)memdup_root( |
| 3352 | 960 | &mem_root, merge_val.data(), merge_val.size()); | |
| 3353 |
1/2✓ Branch 0 taken 960 times.
✗ Branch 1 not taken.
|
960 | keys.emplace_back(rocksdb::Slice(key, merge_key.size()), |
| 3354 | 1920 | rocksdb::Slice(val, merge_val.size())); | |
| 3355 | } | ||
| 3356 | } | ||
| 3357 | |||
| 3358 |
2/2✓ Branch 0 taken 360 times.
✓ Branch 1 taken 960 times.
|
1320 | if (materialized) { |
| 3359 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | rc2 = sst_info->put(merge_key, merge_val); |
| 3360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
|
360 | if (rc != 0) { |
| 3361 | ✗ | rc = rc2; | |
| 3362 | ✗ | break; | |
| 3363 | } | ||
| 3364 | } | ||
| 3365 | |||
| 3366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1320 times.
|
1320 | if (rc2) break; |
| 3367 | } | ||
| 3368 | |||
| 3369 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
|
24 | if (!rc2 && keydef->m_is_reverse_cf && materialized) { |
| 3370 | // Write sentinel before moving to next prefix. | ||
| 3371 | ✗ | rc2 = sst_info->put(cur_prefix, rocksdb::Slice()); | |
| 3372 | ✗ | if (rc2 != 0) { | |
| 3373 | ✗ | break; | |
| 3374 | } | ||
| 3375 | } | ||
| 3376 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
24 | } else { |
| 3377 | 445 | struct unique_sk_buf_info sk_info; | |
| 3378 | |||
| 3379 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 418 times.
|
445 | if (is_unique_index) { |
| 3380 | 27 | uint max_packed_sk_len = keydef->max_storage_fmt_length(); | |
| 3381 | 27 | sk_info.dup_sk_buf = reinterpret_cast<uchar *>( | |
| 3382 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0))); |
| 3383 | 27 | sk_info.dup_sk_buf_old = reinterpret_cast<uchar *>( | |
| 3384 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0))); |
| 3385 | } | ||
| 3386 | |||
| 3387 |
3/4✓ Branch 0 taken 24079945 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24079515 times.
✓ Branch 3 taken 430 times.
|
24079945 | while ((rc2 = rdb_merge.next(&merge_key, &merge_val)) == 0) { |
| 3388 | /* Perform uniqueness check if needed */ | ||
| 3389 |
4/4✓ Branch 0 taken 66 times.
✓ Branch 1 taken 24079449 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 24079500 times.
|
24079581 | if (is_unique_index && |
| 3390 |
3/4✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 51 times.
|
66 | check_duplicate_sk(table_arg, *keydef, &merge_key, &sk_info)) { |
| 3391 | /* | ||
| 3392 | Duplicate entry found when trying to create unique secondary | ||
| 3393 | key. We need to unpack the record into new_table_arg->record[0] | ||
| 3394 | as it is used inside print_keydup_error so that the error | ||
| 3395 | message shows the duplicate record. | ||
| 3396 | */ | ||
| 3397 |
2/4✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
|
15 | if (keydef->unpack_record(table_arg, table_arg->record[0], |
| 3398 | &merge_key, &merge_val, false)) { | ||
| 3399 | /* Should never reach here */ | ||
| 3400 | ✗ | assert(0); | |
| 3401 | } | ||
| 3402 | |||
| 3403 | 15 | rc = ER_DUP_ENTRY; | |
| 3404 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | if (is_critical_error) { |
| 3405 | 15 | *is_critical_error = false; | |
| 3406 | } | ||
| 3407 | 15 | break; | |
| 3408 | } | ||
| 3409 | |||
| 3410 | /* | ||
| 3411 | Insert key and slice to SST via SSTFileWriter API. | ||
| 3412 | */ | ||
| 3413 |
2/4✓ Branch 0 taken 24079500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24079500 times.
|
24079500 | if ((rc2 = sst_info->put(merge_key, merge_val)) != 0) { |
| 3414 | ✗ | rc = rc2; | |
| 3415 | |||
| 3416 | // Don't return yet - make sure we finish the sst_info | ||
| 3417 | ✗ | break; | |
| 3418 | } | ||
| 3419 | } | ||
| 3420 | 445 | } | |
| 3421 | |||
| 3422 | // -1 => no more items | ||
| 3423 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
469 | if (rc2 > 0 && rc == 0) { |
| 3424 | ✗ | rc = rc2; | |
| 3425 | } | ||
| 3426 | |||
| 3427 | 469 | Rdb_sst_info::Rdb_sst_commit_info commit_info; | |
| 3428 |
1/2✓ Branch 0 taken 469 times.
✗ Branch 1 not taken.
|
469 | rc2 = sst_info->finish(&commit_info, print_client_error); |
| 3429 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 469 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
469 | if (rc2 != 0 && rc == 0) { |
| 3430 | // Only set the error from sst_info->finish if finish failed and we | ||
| 3431 | // didn't fail before. In other words, we don't have finish's | ||
| 3432 | // success mask earlier failures | ||
| 3433 | ✗ | rc = rc2; | |
| 3434 | } | ||
| 3435 | |||
| 3436 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 454 times.
|
469 | if (rc) { |
| 3437 | 15 | return rc; | |
| 3438 | } | ||
| 3439 | |||
| 3440 |
1/2✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
|
454 | if (commit_info.has_work()) { |
| 3441 |
1/2✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
|
454 | sst_commit_list.emplace_back(std::move(commit_info)); |
| 3442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 454 times.
|
454 | assert(!commit_info.has_work()); |
| 3443 | } | ||
| 3444 |
8/14✓ Branch 0 taken 454 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 454 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 454 times.
✓ Branch 7 taken 21 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 454 times.
✓ Branch 11 taken 21 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
526 | } |
| 3445 | |||
| 3446 |
2/4✓ Branch 0 taken 412 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 412 times.
|
412 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3447 | // NO_LINT_DEBUG | ||
| 3448 | ✗ | LogPluginErrMsg( | |
| 3449 | INFORMATION_LEVEL, 0, | ||
| 3450 | "SST Tracing : Flushing index_merge sort buffer completed"); | ||
| 3451 | } | ||
| 3452 |
2/2✓ Branch 0 taken 412 times.
✓ Branch 1 taken 21 times.
|
433 | } |
| 3453 | |||
| 3454 | // Early return in case we lost the race completely and end up with no | ||
| 3455 | // work at all | ||
| 3456 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 501 times.
|
508 | if (sst_commit_list.size() == 0) { |
| 3457 | 7 | return rc; | |
| 3458 | } | ||
| 3459 | |||
| 3460 | // INGEST phase: Group all Rdb_sst_commit_info by cf (as they might | ||
| 3461 | // have the same cf across different indexes) and call out to RocksDB | ||
| 3462 | // to ingest all SST files in one atomic operation | ||
| 3463 | 501 | rocksdb::IngestExternalFileOptions options; | |
| 3464 | 501 | options.move_files = true; | |
| 3465 | 501 | options.snapshot_consistency = false; | |
| 3466 | 501 | options.allow_global_seqno = false; | |
| 3467 | 501 | options.allow_blocking_flush = false; | |
| 3468 | |||
| 3469 | std::map<rocksdb::ColumnFamilyHandle *, rocksdb::IngestExternalFileArg> | ||
| 3470 | 501 | arg_map; | |
| 3471 | |||
| 3472 | // Group by column_family | ||
| 3473 |
2/2✓ Branch 0 taken 594 times.
✓ Branch 1 taken 501 times.
|
1095 | for (auto &commit_info : sst_commit_list) { |
| 3474 |
3/4✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 522 times.
✓ Branch 3 taken 72 times.
|
594 | if (arg_map.find(commit_info.get_cf()) == arg_map.end()) { |
| 3475 | 522 | rocksdb::IngestExternalFileArg arg; | |
| 3476 | 522 | arg.column_family = commit_info.get_cf(), | |
| 3477 |
1/2✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
|
522 | arg.external_files = commit_info.get_committed_files(), |
| 3478 | 522 | arg.options = options; | |
| 3479 | |||
| 3480 |
1/2✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
|
522 | arg_map.emplace(commit_info.get_cf(), arg); |
| 3481 | 522 | } else { | |
| 3482 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | auto &files = arg_map[commit_info.get_cf()].external_files; |
| 3483 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | files.insert(files.end(), commit_info.get_committed_files().begin(), |
| 3484 | 72 | commit_info.get_committed_files().end()); | |
| 3485 | } | ||
| 3486 | } | ||
| 3487 | |||
| 3488 | 501 | std::vector<rocksdb::IngestExternalFileArg> args; | |
| 3489 | 501 | size_t file_count = 0; | |
| 3490 |
2/2✓ Branch 0 taken 522 times.
✓ Branch 1 taken 501 times.
|
1023 | for (auto &cf_files_pair : arg_map) { |
| 3491 |
1/2✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
|
522 | args.push_back(cf_files_pair.second); |
| 3492 | 522 | file_count += cf_files_pair.second.external_files.size(); | |
| 3493 | } | ||
| 3494 | |||
| 3495 |
2/4✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 501 times.
|
501 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3496 | // NO_LINT_DEBUG | ||
| 3497 | ✗ | LogPluginErrMsg( | |
| 3498 | INFORMATION_LEVEL, 0, | ||
| 3499 | "SST Tracing: Calling IngestExternalFile with '%zu' files", | ||
| 3500 | file_count); | ||
| 3501 | } | ||
| 3502 |
1/2✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
|
501 | const rocksdb::Status s = rdb->IngestExternalFiles(args); |
| 3503 |
2/4✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 501 times.
|
501 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3504 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 3505 | "SST Tracing: IngestExternalFile '%zu' files returned %s", | ||
| 3506 | file_count, s.ok() ? "ok" : "not ok"); | ||
| 3507 | } | ||
| 3508 | |||
| 3509 |
3/4✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 492 times.
|
501 | if (!s.ok()) { |
| 3510 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | if (print_client_error) { |
| 3511 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | Rdb_sst_info::report_error_msg(s, nullptr); |
| 3512 | } | ||
| 3513 | 9 | return HA_ERR_ROCKSDB_BULK_LOAD; | |
| 3514 | } | ||
| 3515 | |||
| 3516 | // COMMIT phase: mark everything as completed. This avoids SST file | ||
| 3517 | // deletion kicking in. Otherwise SST files would get deleted if this | ||
| 3518 | // entire operation is aborted | ||
| 3519 |
2/2✓ Branch 0 taken 585 times.
✓ Branch 1 taken 492 times.
|
1077 | for (auto &commit_info : sst_commit_list) { |
| 3520 | 585 | commit_info.commit(); | |
| 3521 | } | ||
| 3522 | |||
| 3523 |
2/4✓ Branch 0 taken 492 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 492 times.
|
492 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3524 | // NO_LINT_DEBUG | ||
| 3525 | ✗ | LogPluginErrMsg( | |
| 3526 | INFORMATION_LEVEL, 0, | ||
| 3527 | "SST Tracing : Bulk loading operation completed for table '%s'", | ||
| 3528 | m_curr_bulk_load_tablename.c_str()); | ||
| 3529 | } | ||
| 3530 | |||
| 3531 | 492 | return rc; | |
| 3532 | 529 | } | |
| 3533 | |||
| 3534 | /** | ||
| 3535 | Check whether secondary key value is duplicate or not | ||
| 3536 | |||
| 3537 | @param[in] table_arg the table currently working on | ||
| 3538 | @param[in key_def the key_def is being checked | ||
| 3539 | @param[in] key secondary key storage data | ||
| 3540 | @param[out] sk_info hold secondary key memcmp datas(new/old) | ||
| 3541 | @return | ||
| 3542 | HA_EXIT_SUCCESS OK | ||
| 3543 | other HA_ERR error code (can be SE-specific) | ||
| 3544 | */ | ||
| 3545 | |||
| 3546 | 66 | int check_duplicate_sk(const TABLE *table_arg, const Rdb_key_def &key_def, | |
| 3547 | const rocksdb::Slice *key, | ||
| 3548 | struct unique_sk_buf_info *sk_info) { | ||
| 3549 | 66 | uint n_null_fields = 0; | |
| 3550 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | const rocksdb::Comparator *index_comp = key_def.get_cf()->GetComparator(); |
| 3551 | |||
| 3552 | /* Get proper SK buffer. */ | ||
| 3553 | 66 | uchar *sk_buf = sk_info->swap_and_get_sk_buf(); | |
| 3554 | |||
| 3555 | /* Get memcmp form of sk without extended pk tail */ | ||
| 3556 | uint sk_memcmp_size = | ||
| 3557 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | key_def.get_memcmp_sk_parts(table_arg, *key, sk_buf, &n_null_fields); |
| 3558 | |||
| 3559 | 66 | sk_info->sk_memcmp_key = | |
| 3560 | 66 | rocksdb::Slice(reinterpret_cast<char *>(sk_buf), sk_memcmp_size); | |
| 3561 | |||
| 3562 |
6/6✓ Branch 0 taken 39 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 51 times.
|
96 | if (sk_info->sk_memcmp_key_old.size() > 0 && n_null_fields == 0 && |
| 3563 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
|
30 | index_comp->Compare(sk_info->sk_memcmp_key, |
| 3564 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | sk_info->sk_memcmp_key_old) == 0) { |
| 3565 | 15 | return 1; | |
| 3566 | } | ||
| 3567 | |||
| 3568 | 51 | sk_info->sk_memcmp_key_old = sk_info->sk_memcmp_key; | |
| 3569 | 51 | return 0; | |
| 3570 | } | ||
| 3571 | |||
| 3572 | 589 | int start_bulk_load(ha_rocksdb *const bulk_load, | |
| 3573 | std::shared_ptr<Rdb_sst_info> sst_info) { | ||
| 3574 | /* | ||
| 3575 | If we already have an open bulk load of a table and the name doesn't | ||
| 3576 | match the current one, close out the currently running one. This allows | ||
| 3577 | multiple bulk loads to occur on a partitioned table, but then closes | ||
| 3578 | them all out when we switch to another table. | ||
| 3579 | */ | ||
| 3580 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
|
589 | assert(bulk_load != nullptr); |
| 3581 | |||
| 3582 |
6/6✓ Branch 0 taken 114 times.
✓ Branch 1 taken 475 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 57 times.
✓ Branch 5 taken 532 times.
|
703 | if (!m_curr_bulk_load.empty() && |
| 3583 | 114 | bulk_load->get_table_basename() != m_curr_bulk_load_tablename) { | |
| 3584 | 57 | const auto res = finish_bulk_load(); | |
| 3585 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 54 times.
|
57 | if (res != HA_EXIT_SUCCESS) { |
| 3586 | 3 | return res; | |
| 3587 | } | ||
| 3588 | } | ||
| 3589 | |||
| 3590 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 583 times.
|
586 | if (THDVAR(m_thd, trace_sst_api)) { |
| 3591 | // NO_LINT_DEBUG | ||
| 3592 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg( |
| 3593 | INFORMATION_LEVEL, 0, | ||
| 3594 | "SST Tracing : Starting bulk loading operation for table '%s'", | ||
| 3595 | bulk_load->get_table_basename().c_str()); | ||
| 3596 | } | ||
| 3597 | |||
| 3598 | /* | ||
| 3599 | This used to track ha_rocksdb handler objects, but those can be | ||
| 3600 | freed by the table cache while this was referencing them. Instead | ||
| 3601 | of tracking ha_rocksdb handler objects, this now tracks the | ||
| 3602 | Rdb_sst_info allocated, and both the ha_rocksdb handler and the | ||
| 3603 | Rdb_transaction both have shared pointers to them. | ||
| 3604 | |||
| 3605 | On transaction complete, it will commit each Rdb_sst_info structure found. | ||
| 3606 | If the ha_rocksdb object is freed, etc., it will also commit | ||
| 3607 | the Rdb_sst_info. The Rdb_sst_info commit path needs to be idempotent. | ||
| 3608 | */ | ||
| 3609 | 586 | m_curr_bulk_load.push_back(sst_info); | |
| 3610 | 586 | m_curr_bulk_load_tablename = bulk_load->get_table_basename(); | |
| 3611 | 586 | return HA_EXIT_SUCCESS; | |
| 3612 | } | ||
| 3613 | |||
| 3614 | 167 | int num_ongoing_bulk_load() const { return m_curr_bulk_load.size(); } | |
| 3615 | |||
| 3616 | 475 | const char *get_rocksdb_tmpdir() const { | |
| 3617 | 475 | const char *tmp_dir = THDVAR(get_thd(), tmpdir); | |
| 3618 | |||
| 3619 | /* | ||
| 3620 | We want to treat an empty string as nullptr, in these cases DDL operations | ||
| 3621 | will use the default --tmpdir passed to mysql instead. | ||
| 3622 | */ | ||
| 3623 |
2/4✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
|
475 | if (tmp_dir != nullptr && *tmp_dir == '\0') { |
| 3624 | 475 | tmp_dir = nullptr; | |
| 3625 | } | ||
| 3626 | 475 | return (tmp_dir); | |
| 3627 | } | ||
| 3628 | |||
| 3629 | /* | ||
| 3630 | Flush the data accumulated so far. This assumes we're doing a bulk insert. | ||
| 3631 | |||
| 3632 | @detail | ||
| 3633 | This should work like transaction commit, except that we don't | ||
| 3634 | synchronize with the binlog (there is no API that would allow to have | ||
| 3635 | binlog flush the changes accumulated so far and return its current | ||
| 3636 | position) | ||
| 3637 | |||
| 3638 | @todo | ||
| 3639 | Add test coverage for what happens when somebody attempts to do bulk | ||
| 3640 | inserts while inside a multi-statement transaction. | ||
| 3641 | */ | ||
| 3642 | 478 | bool flush_batch() { | |
| 3643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
|
478 | if (get_write_count() == 0) return false; |
| 3644 | |||
| 3645 | /* Commit the current transaction */ | ||
| 3646 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
|
478 | if (commit_no_binlog()) return true; |
| 3647 | |||
| 3648 |
1/2✓ Branch 0 taken 478 times.
✗ Branch 1 not taken.
|
478 | DEBUG_SYNC(m_thd, "rocksdb.flush_batch"); |
| 3649 | |||
| 3650 | /* Start another one */ | ||
| 3651 | 478 | start_tx(); | |
| 3652 | 478 | return false; | |
| 3653 | } | ||
| 3654 | |||
| 3655 | 8164663 | void set_auto_incr(const GL_INDEX_ID &gl_index_id, ulonglong curr_id) { | |
| 3656 | 16412021 | m_auto_incr_map[gl_index_id] = | |
| 3657 | 8164663 | std::max(m_auto_incr_map[gl_index_id], curr_id); | |
| 3658 | 8254188 | } | |
| 3659 | |||
| 3660 | #ifndef NDEBUG | ||
| 3661 | 410 | ulonglong get_auto_incr(const GL_INDEX_ID &gl_index_id) { | |
| 3662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 410 times.
|
410 | if (m_auto_incr_map.count(gl_index_id) > 0) { |
| 3663 | ✗ | return m_auto_incr_map[gl_index_id]; | |
| 3664 | } | ||
| 3665 | 410 | return 0; | |
| 3666 | } | ||
| 3667 | #endif | ||
| 3668 | |||
| 3669 | virtual rocksdb::Status put(rocksdb::ColumnFamilyHandle *const column_family, | ||
| 3670 | const rocksdb::Slice &key, | ||
| 3671 | const rocksdb::Slice &value, | ||
| 3672 | const bool assume_tracked) = 0; | ||
| 3673 | virtual rocksdb::Status delete_key( | ||
| 3674 | rocksdb::ColumnFamilyHandle *const column_family, | ||
| 3675 | const rocksdb::Slice &key, const bool assume_tracked) = 0; | ||
| 3676 | virtual rocksdb::Status single_delete( | ||
| 3677 | rocksdb::ColumnFamilyHandle *const column_family, | ||
| 3678 | const rocksdb::Slice &key, const bool assume_tracked) = 0; | ||
| 3679 | |||
| 3680 | virtual bool has_modifications() const = 0; | ||
| 3681 | |||
| 3682 | virtual rocksdb::WriteBatchBase *get_indexed_write_batch() = 0; | ||
| 3683 | /* | ||
| 3684 | Return a WriteBatch that one can write to. The writes will skip any | ||
| 3685 | transaction locking. The writes will NOT be visible to the transaction. | ||
| 3686 | */ | ||
| 3687 | rocksdb::WriteBatchBase *get_blind_write_batch() { | ||
| 3688 | return get_indexed_write_batch()->GetWriteBatch(); | ||
| 3689 | } | ||
| 3690 | |||
| 3691 | virtual rocksdb::Status get(rocksdb::ColumnFamilyHandle *const column_family, | ||
| 3692 | const rocksdb::Slice &key, | ||
| 3693 | rocksdb::PinnableSlice *const value) const = 0; | ||
| 3694 | virtual rocksdb::Status get_for_update(const Rdb_key_def &key_descr, | ||
| 3695 | const rocksdb::Slice &key, | ||
| 3696 | rocksdb::PinnableSlice *const value, | ||
| 3697 | bool exclusive, const bool do_validate, | ||
| 3698 | bool no_wait) = 0; | ||
| 3699 | |||
| 3700 | 262898 | rocksdb::Iterator *get_iterator( | |
| 3701 | rocksdb::ColumnFamilyHandle *const column_family, bool skip_bloom_filter, | ||
| 3702 | const rocksdb::Slice &eq_cond_lower_bound, | ||
| 3703 | const rocksdb::Slice &eq_cond_upper_bound, bool read_current = false, | ||
| 3704 | bool create_snapshot = true) { | ||
| 3705 | // Make sure we are not doing both read_current (which implies we don't | ||
| 3706 | // want a snapshot) and create_snapshot which makes sure we create | ||
| 3707 | // a snapshot | ||
| 3708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 262898 times.
|
262898 | assert(column_family != nullptr); |
| 3709 |
3/4✓ Branch 0 taken 10525 times.
✓ Branch 1 taken 252373 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10525 times.
|
262898 | assert(!read_current || !create_snapshot); |
| 3710 | |||
| 3711 |
3/4✓ Branch 0 taken 252373 times.
✓ Branch 1 taken 10525 times.
✓ Branch 2 taken 252373 times.
✗ Branch 3 not taken.
|
262898 | if (create_snapshot) acquire_snapshot(true); |
| 3712 | |||
| 3713 |
1/2✓ Branch 0 taken 262898 times.
✗ Branch 1 not taken.
|
262898 | rocksdb::ReadOptions options = m_read_opts; |
| 3714 |
1/2✓ Branch 0 taken 262898 times.
✗ Branch 1 not taken.
|
262898 | const bool fill_cache = !THDVAR(get_thd(), skip_fill_cache); |
| 3715 | |||
| 3716 |
2/2✓ Branch 0 taken 200306 times.
✓ Branch 1 taken 62592 times.
|
262898 | if (skip_bloom_filter) { |
| 3717 | const bool enable_iterate_bounds = | ||
| 3718 |
1/2✓ Branch 0 taken 200306 times.
✗ Branch 1 not taken.
|
200306 | THDVAR(get_thd(), enable_iterate_bounds); |
| 3719 | 200306 | options.total_order_seek = true; | |
| 3720 | 200306 | options.iterate_lower_bound = | |
| 3721 |
2/2✓ Branch 0 taken 200297 times.
✓ Branch 1 taken 9 times.
|
200306 | enable_iterate_bounds ? &eq_cond_lower_bound : nullptr; |
| 3722 | 200306 | options.iterate_upper_bound = | |
| 3723 |
2/2✓ Branch 0 taken 200297 times.
✓ Branch 1 taken 9 times.
|
200306 | enable_iterate_bounds ? &eq_cond_upper_bound : nullptr; |
| 3724 | } else { | ||
| 3725 | // With this option, Iterator::Valid() returns false if key | ||
| 3726 | // is outside of the prefix bloom filter range set at Seek(). | ||
| 3727 | // Must not be set to true if not using bloom filter. | ||
| 3728 | 62592 | options.prefix_same_as_start = true; | |
| 3729 | } | ||
| 3730 | 262898 | options.fill_cache = fill_cache; | |
| 3731 |
2/2✓ Branch 0 taken 10525 times.
✓ Branch 1 taken 252373 times.
|
262898 | if (read_current) { |
| 3732 | 10525 | options.snapshot = nullptr; | |
| 3733 | } | ||
| 3734 |
1/2✓ Branch 0 taken 262898 times.
✗ Branch 1 not taken.
|
525796 | return get_iterator(options, column_family); |
| 3735 | 262898 | } | |
| 3736 | |||
| 3737 | virtual bool is_tx_started() const = 0; | ||
| 3738 | virtual void start_tx() = 0; | ||
| 3739 | virtual void start_stmt() = 0; | ||
| 3740 | virtual void set_name() = 0; | ||
| 3741 | |||
| 3742 | protected: | ||
| 3743 | // Non-virtual functions with actions to be done on transaction start and | ||
| 3744 | // commit. | ||
| 3745 | 3432330 | void on_commit() { | |
| 3746 | time_t tm; | ||
| 3747 | 3432330 | tm = time(nullptr); | |
| 3748 |
2/2✓ Branch 0 taken 3433069 times.
✓ Branch 1 taken 3432330 times.
|
6865399 | for (auto &it : modified_tables) { |
| 3749 | 3433069 | it->m_update_time = tm; | |
| 3750 | } | ||
| 3751 | 3432330 | modified_tables.clear(); | |
| 3752 | 3432330 | } | |
| 3753 | 7141186 | void on_rollback() { modified_tables.clear(); } | |
| 3754 | |||
| 3755 | public: | ||
| 3756 | 70948633 | void log_table_write_op(Rdb_tbl_def *tbl) { modified_tables.insert(tbl); } | |
| 3757 | |||
| 3758 | 3580605 | void set_initial_savepoint() { | |
| 3759 | /* | ||
| 3760 | Set the initial savepoint. If the first statement in the transaction | ||
| 3761 | fails, we need something to roll back to, without rolling back the | ||
| 3762 | entire transaction. | ||
| 3763 | */ | ||
| 3764 | 3580605 | do_set_savepoint(); | |
| 3765 | 3580897 | m_writes_at_last_savepoint = m_write_count; | |
| 3766 | 3580897 | } | |
| 3767 | |||
| 3768 | /* | ||
| 3769 | Called when a "top-level" statement inside a transaction completes | ||
| 3770 | successfully and its changes become part of the transaction's changes. | ||
| 3771 | */ | ||
| 3772 | 836497 | int make_stmt_savepoint_permanent() { | |
| 3773 | // Take another RocksDB savepoint only if we had changes since the last | ||
| 3774 | // one. This is very important for long transactions doing lots of | ||
| 3775 | // SELECTs. | ||
| 3776 |
2/2✓ Branch 0 taken 49456 times.
✓ Branch 1 taken 787041 times.
|
836497 | if (m_writes_at_last_savepoint != m_write_count) { |
| 3777 |
1/2✓ Branch 0 taken 49456 times.
✗ Branch 1 not taken.
|
49456 | rocksdb::Status status = rocksdb::Status::NotFound(); |
| 3778 |
4/6✓ Branch 0 taken 98912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98912 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 49456 times.
✓ Branch 5 taken 49456 times.
|
98912 | while ((status = do_pop_savepoint()) == rocksdb::Status::OK()) { |
| 3779 | } | ||
| 3780 | |||
| 3781 |
3/6✓ Branch 0 taken 49456 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49456 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 49456 times.
|
49456 | if (status != rocksdb::Status::NotFound()) { |
| 3782 | ✗ | return HA_EXIT_FAILURE; | |
| 3783 | } | ||
| 3784 | |||
| 3785 |
1/2✓ Branch 0 taken 49456 times.
✗ Branch 1 not taken.
|
49456 | do_set_savepoint(); |
| 3786 | 49456 | m_writes_at_last_savepoint = m_write_count; | |
| 3787 |
1/2✓ Branch 0 taken 49456 times.
✗ Branch 1 not taken.
|
49456 | } |
| 3788 | |||
| 3789 | 836497 | return HA_EXIT_SUCCESS; | |
| 3790 | } | ||
| 3791 | |||
| 3792 | /* | ||
| 3793 | Rollback to the savepoint we've set before the last statement | ||
| 3794 | */ | ||
| 3795 | 3386 | void rollback_to_stmt_savepoint() { | |
| 3796 |
2/2✓ Branch 0 taken 138 times.
✓ Branch 1 taken 3248 times.
|
3386 | if (m_writes_at_last_savepoint != m_write_count) { |
| 3797 | 138 | do_rollback_to_savepoint(); | |
| 3798 | /* | ||
| 3799 | RollbackToSavePoint "removes the most recent SetSavePoint()", so | ||
| 3800 | we need to set it again so that next statement can roll back to this | ||
| 3801 | stage. | ||
| 3802 | It's ok to do it here at statement end (instead of doing it at next | ||
| 3803 | statement start) because setting a savepoint is cheap. | ||
| 3804 | */ | ||
| 3805 | 138 | do_set_savepoint(); | |
| 3806 | 138 | m_write_count = m_writes_at_last_savepoint; | |
| 3807 | } | ||
| 3808 | 3386 | } | |
| 3809 | |||
| 3810 | virtual void rollback_stmt() = 0; | ||
| 3811 | |||
| 3812 | 424162 | void set_tx_failed(bool failed_arg) { m_is_tx_failed = failed_arg; } | |
| 3813 | |||
| 3814 | 3854694 | bool can_prepare() const { | |
| 3815 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 3854667 times.
|
3854694 | if (m_rollback_only) { |
| 3816 | 27 | my_error(ER_ROLLBACK_ONLY, MYF(0)); | |
| 3817 | 27 | return false; | |
| 3818 | } | ||
| 3819 | 3854667 | return true; | |
| 3820 | } | ||
| 3821 | |||
| 3822 | 45 | int rollback_to_savepoint(void *const savepoint) { | |
| 3823 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 18 times.
|
45 | if (has_modifications()) { |
| 3824 | 27 | my_error(ER_ROLLBACK_TO_SAVEPOINT, MYF(0)); | |
| 3825 | 27 | m_rollback_only = true; | |
| 3826 | 27 | return HA_EXIT_FAILURE; | |
| 3827 | } | ||
| 3828 | 18 | return HA_EXIT_SUCCESS; | |
| 3829 | } | ||
| 3830 | |||
| 3831 | /* | ||
| 3832 | This is used by transactions started with "START TRANSACTION WITH " | ||
| 3833 | "CONSISTENT [ROCKSDB] SNAPSHOT". When tx_read_only is turned on, | ||
| 3834 | snapshot has to be created via DB::GetSnapshot(), not via Transaction | ||
| 3835 | API. | ||
| 3836 | */ | ||
| 3837 | 11621300 | bool is_tx_read_only() const { return m_tx_read_only; } | |
| 3838 | |||
| 3839 | 3587499 | void set_tx_read_only(bool val) { m_tx_read_only = val; } | |
| 3840 | |||
| 3841 | /* | ||
| 3842 | Add or remove from the global list of active transactions | ||
| 3843 | needed by information_schema queries. | ||
| 3844 | */ | ||
| 3845 | 2576 | void add_to_global_trx_list() { | |
| 3846 | 2576 | RDB_MUTEX_LOCK_CHECK(s_tx_list_mutex); | |
| 3847 |
1/2✓ Branch 0 taken 2579 times.
✗ Branch 1 not taken.
|
2579 | s_tx_list.insert(this); |
| 3848 | 2579 | RDB_MUTEX_UNLOCK_CHECK(s_tx_list_mutex); | |
| 3849 | 2579 | } | |
| 3850 | |||
| 3851 | 2534 | void remove_from_global_trx_list(void) { | |
| 3852 |
9/16✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2533 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
|
2534 | DBUG_EXECUTE_IF("rocksdb_trx_list_crash", { |
| 3853 | THD *thd = new THD(); | ||
| 3854 | thd->thread_stack = reinterpret_cast<char *>(&(thd)); | ||
| 3855 | thd->store_globals(); | ||
| 3856 | |||
| 3857 | const char act[] = | ||
| 3858 | "now signal destructor_started wait_for trx_list_query"; | ||
| 3859 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 3860 | |||
| 3861 | thd->restore_globals(); | ||
| 3862 | delete thd; | ||
| 3863 | }); | ||
| 3864 | 2536 | RDB_MUTEX_LOCK_CHECK(s_tx_list_mutex); | |
| 3865 |
1/2✓ Branch 0 taken 2537 times.
✗ Branch 1 not taken.
|
2537 | s_tx_list.erase(this); |
| 3866 | 2537 | RDB_MUTEX_UNLOCK_CHECK(s_tx_list_mutex); | |
| 3867 | 2537 | } | |
| 3868 | |||
| 3869 | 2579 | explicit Rdb_transaction(THD *const thd) | |
| 3870 |
1/2✓ Branch 0 taken 2576 times.
✗ Branch 1 not taken.
|
2579 | : m_thd(thd), m_tbl_io_perf(nullptr) {} |
| 3871 | |||
| 3872 | 5054 | virtual ~Rdb_transaction() { | |
| 3873 | #ifndef DEBUG_OFF | ||
| 3874 | 5054 | RDB_MUTEX_LOCK_CHECK(s_tx_list_mutex); | |
| 3875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2537 times.
|
5074 | assert(s_tx_list.find(this) == s_tx_list.end()); |
| 3876 | 5074 | RDB_MUTEX_UNLOCK_CHECK(s_tx_list_mutex); | |
| 3877 | #endif | ||
| 3878 | } | ||
| 3879 | }; | ||
| 3880 | |||
| 3881 | #ifndef NDEBUG | ||
| 3882 | // simulate that RocksDB has reported corrupted data | ||
| 3883 | ✗ | static void dbug_change_status_to_corrupted(rocksdb::Status *status) { | |
| 3884 | ✗ | *status = rocksdb::Status::Corruption(); | |
| 3885 | } | ||
| 3886 | ✗ | static void dbug_change_status_to_io_error(rocksdb::Status *status) { | |
| 3887 | ✗ | *status = rocksdb::Status::IOError(); | |
| 3888 | } | ||
| 3889 | ✗ | static void dbug_change_status_to_incomplete(rocksdb::Status *status) { | |
| 3890 | ✗ | *status = rocksdb::Status::Incomplete(); | |
| 3891 | } | ||
| 3892 | #endif | ||
| 3893 | |||
| 3894 | 3581134 | static void fix_write_disable_wal_value(THD *thd, bool sync) { | |
| 3895 | // check if we should switch back to write_disable_wal_save | ||
| 3896 |
6/6✓ Branch 0 taken 111194 times.
✓ Branch 1 taken 3469940 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 111300 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3581240 times.
|
3581134 | if (!sync && THDVAR(thd, write_disable_wal_save)) { |
| 3897 | 3 | THDVAR(thd, write_disable_wal) = THDVAR(thd, write_disable_wal_save); | |
| 3898 | 3 | THDVAR(thd, write_disable_wal_save) = false; | |
| 3899 |
8/16✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
|
3 | LogPluginErrMsg(WARNING_LEVEL, 0, |
| 3900 | "Sync writes disabled. Switching back to " | ||
| 3901 | "rocksdb_write_disable_wal = true"); | ||
| 3902 | } | ||
| 3903 | |||
| 3904 |
6/6✓ Branch 0 taken 3469871 times.
✓ Branch 1 taken 111372 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3469989 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3581361 times.
|
3581243 | if (sync && THDVAR(thd, write_disable_wal)) { |
| 3905 | // write_disable_wal and write_opts.sync are not compatible | ||
| 3906 | // let's remember real session value of write_disable_wal | ||
| 3907 | // and fall back to the compatible one | ||
| 3908 | // We will switch back to the real session value once the global | ||
| 3909 | // rocksdb_flush_log_at_trx_commit is compatible again | ||
| 3910 | 3 | THDVAR(thd, write_disable_wal_save) = THDVAR(thd, write_disable_wal); | |
| 3911 | |||
| 3912 | 3 | THDVAR(thd, write_disable_wal) = false; | |
| 3913 |
8/16✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
|
3 | LogPluginErrMsg( |
| 3914 | WARNING_LEVEL, 0, | ||
| 3915 | "Sync writes has to enable WAL. Switching to rocksdb_write_disable_wal " | ||
| 3916 | "= false for the time when sync writes are enabled."); | ||
| 3917 | } | ||
| 3918 | 3581364 | } | |
| 3919 | |||
| 3920 | /* | ||
| 3921 | This is a rocksdb transaction. Its members represent the current transaction, | ||
| 3922 | which consists of: | ||
| 3923 | - the snapshot | ||
| 3924 | - the changes we've made but are not seeing yet. | ||
| 3925 | |||
| 3926 | The changes are made to individual tables, which store them here and then | ||
| 3927 | this object commits them on commit. | ||
| 3928 | */ | ||
| 3929 | class Rdb_transaction_impl : public Rdb_transaction { | ||
| 3930 | rocksdb::Transaction *m_rocksdb_tx = nullptr; | ||
| 3931 | rocksdb::Transaction *m_rocksdb_reuse_tx = nullptr; | ||
| 3932 | |||
| 3933 | public: | ||
| 3934 | 112277455 | void set_lock_timeout(int timeout_sec_arg) override { | |
| 3935 |
2/2✓ Branch 0 taken 108740340 times.
✓ Branch 1 taken 3537115 times.
|
112277455 | if (m_rocksdb_tx) { |
| 3936 | 108740340 | m_rocksdb_tx->SetLockTimeout(rdb_convert_sec_to_ms(timeout_sec_arg)); | |
| 3937 | } | ||
| 3938 | 112232218 | } | |
| 3939 | |||
| 3940 | 3432832 | void set_sync(bool sync) override { | |
| 3941 | 3432832 | m_rocksdb_tx->GetWriteOptions()->sync = sync; | |
| 3942 | 3432872 | } | |
| 3943 | |||
| 3944 | 3607375 | void release_lock(const Rdb_key_def &key_descr, const std::string &rowkey, | |
| 3945 | bool force) override { | ||
| 3946 |
5/6✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3607327 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 3607327 times.
✓ Branch 5 taken 48 times.
|
3607375 | if (!THDVAR(m_thd, lock_scanned_rows) || force) { |
| 3947 |
1/2✓ Branch 0 taken 3607327 times.
✗ Branch 1 not taken.
|
3607327 | m_rocksdb_tx->UndoGetForUpdate(key_descr.get_cf(), |
| 3948 | 3607327 | rocksdb::Slice(rowkey)); | |
| 3949 | // row_lock_count track row(pk) | ||
| 3950 |
4/6✓ Branch 0 taken 3606763 times.
✓ Branch 1 taken 564 times.
✓ Branch 2 taken 3606763 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3606763 times.
✗ Branch 5 not taken.
|
3607327 | assert(!key_descr.is_primary_key() || |
| 3951 | (key_descr.is_primary_key() && m_row_lock_count > 0)); | ||
| 3952 | // m_row_lock_count tracks per row data instead of per key data | ||
| 3953 |
5/6✓ Branch 0 taken 3606763 times.
✓ Branch 1 taken 564 times.
✓ Branch 2 taken 3606763 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3606763 times.
✓ Branch 5 taken 564 times.
|
3607327 | if (key_descr.is_primary_key() && m_row_lock_count > 0) { |
| 3954 | 3606763 | m_row_lock_count--; | |
| 3955 | } | ||
| 3956 | } | ||
| 3957 | 3607375 | } | |
| 3958 | |||
| 3959 | 240 | virtual bool is_writebatch_trx() const override { return false; } | |
| 3960 | |||
| 3961 | private: | ||
| 3962 | 3581429 | void release_tx(void) { | |
| 3963 | // We are done with the current active transaction object. Preserve it | ||
| 3964 | // for later reuse. | ||
| 3965 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3581429 times.
|
3581429 | assert(m_rocksdb_reuse_tx == nullptr); |
| 3966 | 3581429 | m_rocksdb_reuse_tx = m_rocksdb_tx; | |
| 3967 | 3581429 | m_rocksdb_tx = nullptr; | |
| 3968 | 3581429 | } | |
| 3969 | |||
| 3970 | 3433389 | bool prepare() override { | |
| 3971 | 3433389 | rocksdb::Status s; | |
| 3972 | |||
| 3973 |
3/6✓ Branch 0 taken 3433403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3433425 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3433574 times.
✗ Branch 5 not taken.
|
3433469 | s = merge_auto_incr_map(m_rocksdb_tx->GetWriteBatch()->GetWriteBatch()); |
| 3974 | #ifndef NDEBUG | ||
| 3975 |
2/6✓ Branch 0 taken 3433467 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3433467 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3433596 | DBUG_EXECUTE_IF("myrocks_prepare_io_error", |
| 3976 | dbug_change_status_to_io_error(&s);); | ||
| 3977 |
2/6✓ Branch 0 taken 3433539 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3433539 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3433467 | DBUG_EXECUTE_IF("myrocks_prepare_incomplete", |
| 3978 | dbug_change_status_to_incomplete(&s);); | ||
| 3979 | #endif | ||
| 3980 |
2/4✓ Branch 0 taken 3433560 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3433560 times.
|
3433539 | if (!s.ok()) { |
| 3981 | std::string msg = | ||
| 3982 | ✗ | "RocksDB error on COMMIT (Prepare/merge): " + s.ToString(); | |
| 3983 | ✗ | my_error(ER_INTERNAL_ERROR, MYF(0), msg.c_str()); | |
| 3984 | ✗ | return false; | |
| 3985 | } | ||
| 3986 | |||
| 3987 |
1/2✓ Branch 0 taken 3433375 times.
✗ Branch 1 not taken.
|
3433560 | s = m_rocksdb_tx->Prepare(); |
| 3988 |
2/4✓ Branch 0 taken 3433471 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3433471 times.
|
3433502 | if (!s.ok()) { |
| 3989 | ✗ | std::string msg = "RocksDB error on COMMIT (Prepare): " + s.ToString(); | |
| 3990 | ✗ | my_error(ER_INTERNAL_ERROR, MYF(0), msg.c_str()); | |
| 3991 | ✗ | return false; | |
| 3992 | } | ||
| 3993 | 3433471 | return true; | |
| 3994 | 3433471 | } | |
| 3995 | |||
| 3996 | 3426328 | bool commit_no_binlog() override { | |
| 3997 | 3426328 | bool res = false; | |
| 3998 | 3426328 | rocksdb::Status s; | |
| 3999 | |||
| 4000 |
3/6✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3426328 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3426328 times.
✗ Branch 5 not taken.
|
3426328 | s = merge_auto_incr_map(m_rocksdb_tx->GetWriteBatch()->GetWriteBatch()); |
| 4001 | #ifndef NDEBUG | ||
| 4002 |
2/6✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3426328 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3426328 | DBUG_EXECUTE_IF("myrocks_commit_merge_io_error", |
| 4003 | dbug_change_status_to_io_error(&s);); | ||
| 4004 |
2/6✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3426328 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3426328 | DBUG_EXECUTE_IF("myrocks_commit_merge_incomplete", |
| 4005 | dbug_change_status_to_incomplete(&s);); | ||
| 4006 | #endif | ||
| 4007 |
2/4✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3426328 times.
|
3426328 | if (!s.ok()) { |
| 4008 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_TX_COMMIT); | |
| 4009 | ✗ | res = true; | |
| 4010 | ✗ | goto error; | |
| 4011 | } | ||
| 4012 | |||
| 4013 |
1/2✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
|
3426328 | release_snapshot(); |
| 4014 |
1/2✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
|
3426328 | s = m_rocksdb_tx->Commit(); |
| 4015 | #ifndef NDEBUG | ||
| 4016 |
2/6✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3426328 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3426328 | DBUG_EXECUTE_IF("myrocks_commit_io_error", |
| 4017 | dbug_change_status_to_io_error(&s);); | ||
| 4018 |
2/6✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3426328 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3426328 | DBUG_EXECUTE_IF("myrocks_commit_incomplete", |
| 4019 | dbug_change_status_to_incomplete(&s);); | ||
| 4020 | #endif | ||
| 4021 |
2/4✓ Branch 0 taken 3426328 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3426328 times.
|
3426328 | if (!s.ok()) { |
| 4022 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_TX_COMMIT); | |
| 4023 | ✗ | res = true; | |
| 4024 | ✗ | goto error; | |
| 4025 | } | ||
| 4026 | |||
| 4027 | 3426328 | on_commit(); | |
| 4028 | 3426328 | error: | |
| 4029 | 3426328 | on_rollback(); | |
| 4030 | /* Save the transaction object to be reused */ | ||
| 4031 | 3426328 | release_tx(); | |
| 4032 | |||
| 4033 | 3426328 | m_write_count = 0; | |
| 4034 | 3426328 | m_row_lock_count = 0; | |
| 4035 | 3426328 | set_tx_read_only(false); | |
| 4036 | 3426328 | m_rollback_only = false; | |
| 4037 | 3426328 | return res; | |
| 4038 | 3426328 | } | |
| 4039 | |||
| 4040 | public: | ||
| 4041 | 3708907 | void rollback() override { | |
| 4042 | 3708907 | on_rollback(); | |
| 4043 | 3708858 | m_write_count = 0; | |
| 4044 | 3708858 | m_row_lock_count = 0; | |
| 4045 | 3708858 | m_auto_incr_map.clear(); | |
| 4046 | 3708815 | m_ddl_transaction = false; | |
| 4047 |
2/2✓ Branch 0 taken 155101 times.
✓ Branch 1 taken 3553714 times.
|
3708815 | if (m_rocksdb_tx) { |
| 4048 | 155101 | release_snapshot(); | |
| 4049 | /* This will also release all of the locks: */ | ||
| 4050 | 155101 | m_rocksdb_tx->Rollback(); | |
| 4051 | |||
| 4052 | /* Save the transaction object to be reused */ | ||
| 4053 | 155101 | release_tx(); | |
| 4054 | |||
| 4055 | 155101 | set_tx_read_only(false); | |
| 4056 | 155101 | m_rollback_only = false; | |
| 4057 | } | ||
| 4058 | 3708815 | } | |
| 4059 | |||
| 4060 | 25995750 | void acquire_snapshot(bool acquire_now) override { | |
| 4061 |
2/2✓ Branch 0 taken 4235981 times.
✓ Branch 1 taken 21759769 times.
|
25995750 | if (m_read_opts.snapshot == nullptr) { |
| 4062 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4235988 times.
|
4235981 | if (is_tx_read_only()) { |
| 4063 | 39 | snapshot_created(rdb->GetSnapshot()); | |
| 4064 |
2/2✓ Branch 0 taken 245582 times.
✓ Branch 1 taken 3990406 times.
|
4235988 | } else if (acquire_now) { |
| 4065 | 245582 | m_rocksdb_tx->SetSnapshot(); | |
| 4066 | 245582 | snapshot_created(m_rocksdb_tx->GetSnapshot()); | |
| 4067 |
2/2✓ Branch 0 taken 3416419 times.
✓ Branch 1 taken 573987 times.
|
3990406 | } else if (!m_is_delayed_snapshot) { |
| 4068 |
1/2✓ Branch 0 taken 3416724 times.
✗ Branch 1 not taken.
|
3416419 | m_rocksdb_tx->SetSnapshotOnNextOperation(m_notifier); |
| 4069 | 3416746 | m_is_delayed_snapshot = true; | |
| 4070 | } | ||
| 4071 | } | ||
| 4072 | 25996140 | } | |
| 4073 | |||
| 4074 | 3712848 | void release_snapshot() override { | |
| 4075 | 3712848 | bool need_clear = m_is_delayed_snapshot; | |
| 4076 | |||
| 4077 |
2/2✓ Branch 0 taken 3552329 times.
✓ Branch 1 taken 160519 times.
|
3712848 | if (m_read_opts.snapshot != nullptr) { |
| 4078 | 3552329 | m_snapshot_timestamp = 0; | |
| 4079 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 3552273 times.
|
3552329 | if (is_tx_read_only()) { |
| 4080 | 56 | rdb->ReleaseSnapshot(m_read_opts.snapshot); | |
| 4081 | 56 | need_clear = false; | |
| 4082 | } else { | ||
| 4083 | 3552273 | need_clear = true; | |
| 4084 | } | ||
| 4085 | 3552329 | m_read_opts.snapshot = nullptr; | |
| 4086 | } | ||
| 4087 | |||
| 4088 |
3/4✓ Branch 0 taken 3558124 times.
✓ Branch 1 taken 154724 times.
✓ Branch 2 taken 3558124 times.
✗ Branch 3 not taken.
|
3712848 | if (need_clear && m_rocksdb_tx != nullptr) m_rocksdb_tx->ClearSnapshot(); |
| 4089 | 3712848 | m_is_delayed_snapshot = false; | |
| 4090 | 3712848 | } | |
| 4091 | |||
| 4092 | bool has_snapshot() { return m_read_opts.snapshot != nullptr; } | ||
| 4093 | |||
| 4094 | 7420854 | rocksdb::Status put(rocksdb::ColumnFamilyHandle *const column_family, | |
| 4095 | const rocksdb::Slice &key, const rocksdb::Slice &value, | ||
| 4096 | const bool assume_tracked) override { | ||
| 4097 | 7420854 | ++m_write_count; | |
| 4098 | 7420854 | return m_rocksdb_tx->Put(column_family, key, value, assume_tracked); | |
| 4099 | } | ||
| 4100 | |||
| 4101 | 280025 | rocksdb::Status delete_key(rocksdb::ColumnFamilyHandle *const column_family, | |
| 4102 | const rocksdb::Slice &key, | ||
| 4103 | const bool assume_tracked) override { | ||
| 4104 | 280025 | ++m_write_count; | |
| 4105 | 280025 | return m_rocksdb_tx->Delete(column_family, key, assume_tracked); | |
| 4106 | } | ||
| 4107 | |||
| 4108 | 104375 | rocksdb::Status single_delete( | |
| 4109 | rocksdb::ColumnFamilyHandle *const column_family, | ||
| 4110 | const rocksdb::Slice &key, const bool assume_tracked) override { | ||
| 4111 | 104375 | ++m_write_count; | |
| 4112 | 104375 | return m_rocksdb_tx->SingleDelete(column_family, key, assume_tracked); | |
| 4113 | } | ||
| 4114 | |||
| 4115 | 45 | bool has_modifications() const override { | |
| 4116 | 45 | return m_rocksdb_tx->GetWriteBatch() && | |
| 4117 |
2/4✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
|
90 | m_rocksdb_tx->GetWriteBatch()->GetWriteBatch() && |
| 4118 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 18 times.
|
90 | m_rocksdb_tx->GetWriteBatch()->GetWriteBatch()->Count() > 0; |
| 4119 | } | ||
| 4120 | |||
| 4121 | ✗ | rocksdb::WriteBatchBase *get_write_batch() override { | |
| 4122 | ✗ | return m_rocksdb_tx->GetCommitTimeWriteBatch(); | |
| 4123 | } | ||
| 4124 | |||
| 4125 | /* | ||
| 4126 | Return a WriteBatch that one can write to. The writes will skip any | ||
| 4127 | transaction locking. The writes WILL be visible to the transaction. | ||
| 4128 | */ | ||
| 4129 | 52977163 | rocksdb::WriteBatchBase *get_indexed_write_batch() override { | |
| 4130 | 52977163 | ++m_write_count; | |
| 4131 | 52977163 | return m_rocksdb_tx->GetWriteBatch(); | |
| 4132 | } | ||
| 4133 | |||
| 4134 | 12100520 | rocksdb::Status get(rocksdb::ColumnFamilyHandle *const column_family, | |
| 4135 | const rocksdb::Slice &key, | ||
| 4136 | rocksdb::PinnableSlice *const value) const override { | ||
| 4137 | // clean PinnableSlice right before Get() for multiple gets per statement | ||
| 4138 | // the resources after the last Get in a statement are cleared in | ||
| 4139 | // handler::reset call | ||
| 4140 | 12100520 | value->Reset(); | |
| 4141 | 12100520 | global_stats.queries[QUERIES_POINT].inc(); | |
| 4142 | 12100520 | return m_rocksdb_tx->Get(m_read_opts, column_family, key, value); | |
| 4143 | } | ||
| 4144 | |||
| 4145 | 12606683 | rocksdb::Status get_for_update(const Rdb_key_def &key_descr, | |
| 4146 | const rocksdb::Slice &key, | ||
| 4147 | rocksdb::PinnableSlice *const value, | ||
| 4148 | bool exclusive, const bool do_validate, | ||
| 4149 | bool no_wait) override { | ||
| 4150 | 12606683 | rocksdb::ColumnFamilyHandle *const column_family = key_descr.get_cf(); | |
| 4151 | /* check row lock limit in a trx */ | ||
| 4152 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12633630 times.
|
12608856 | if (get_row_lock_count() >= get_max_row_lock_count()) { |
| 4153 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | return rocksdb::Status::Aborted(rocksdb::Status::kLockLimit); |
| 4154 | } | ||
| 4155 | |||
| 4156 |
2/2✓ Branch 0 taken 12611246 times.
✓ Branch 1 taken 22384 times.
|
12633630 | if (value != nullptr) { |
| 4157 |
1/2✓ Branch 0 taken 12581852 times.
✗ Branch 1 not taken.
|
12611246 | value->Reset(); |
| 4158 |
5/8✓ Branch 0 taken 12625295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12625292 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
12581852 | DBUG_EXECUTE_IF("rocksdb_check_uniqueness", |
| 4159 | DEBUG_SYNC(m_thd, "rocksdb_after_unpin");); | ||
| 4160 | } | ||
| 4161 | |||
| 4162 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 12647529 times.
|
12647679 | if (no_wait) { |
| 4163 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | set_lock_timeout(0); |
| 4164 | } | ||
| 4165 | 12667899 | auto restore_wait = create_scope_guard([&]() { | |
| 4166 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 12667749 times.
|
12667899 | if (no_wait) { |
| 4167 | 150 | set_lock_timeout(m_timeout_sec); | |
| 4168 | } | ||
| 4169 |
1/2✓ Branch 0 taken 12604347 times.
✗ Branch 1 not taken.
|
12647679 | }); |
| 4170 | |||
| 4171 | 12604347 | rocksdb::Status s; | |
| 4172 | // If snapshot is null, pass it to GetForUpdate and snapshot is | ||
| 4173 | // initialized there. Snapshot validation is skipped in that case. | ||
| 4174 |
4/4✓ Branch 0 taken 9387954 times.
✓ Branch 1 taken 3304805 times.
✓ Branch 2 taken 6308379 times.
✓ Branch 3 taken 3079575 times.
|
12692759 | if (m_read_opts.snapshot == nullptr || do_validate) { |
| 4175 | 9660809 | s = m_rocksdb_tx->GetForUpdate( | |
| 4176 |
1/2✓ Branch 0 taken 9622438 times.
✗ Branch 1 not taken.
|
9613184 | m_read_opts, column_family, key, value, exclusive, |
| 4177 |
4/4✓ Branch 0 taken 6301383 times.
✓ Branch 1 taken 3311801 times.
✓ Branch 2 taken 6294626 times.
✓ Branch 3 taken 6757 times.
|
19235622 | m_read_opts.snapshot ? do_validate : false); |
| 4178 | } else { | ||
| 4179 | // If snapshot is set, and if skipping validation, | ||
| 4180 | // call GetForUpdate without validation and set back old snapshot | ||
| 4181 | 3079575 | auto saved_snapshot = m_read_opts.snapshot; | |
| 4182 | 3079575 | m_read_opts.snapshot = nullptr; | |
| 4183 |
1/2✓ Branch 0 taken 3079575 times.
✗ Branch 1 not taken.
|
6159150 | s = m_rocksdb_tx->GetForUpdate(m_read_opts, column_family, key, value, |
| 4184 | 3079575 | exclusive, false); | |
| 4185 | 3079575 | m_read_opts.snapshot = saved_snapshot; | |
| 4186 | } | ||
| 4187 | |||
| 4188 | // row_lock_count is to track per row instead of per key | ||
| 4189 |
2/2✓ Branch 0 taken 12642302 times.
✓ Branch 1 taken 49320 times.
|
12734122 | if (key_descr.is_primary_key()) incr_row_lock_count(); |
| 4190 | 12676649 | return s; | |
| 4191 | 12739036 | } | |
| 4192 | |||
| 4193 | 259898 | rocksdb::Iterator *get_iterator( | |
| 4194 | const rocksdb::ReadOptions &options, | ||
| 4195 | rocksdb::ColumnFamilyHandle *const column_family) override { | ||
| 4196 | 259898 | global_stats.queries[QUERIES_RANGE].inc(); | |
| 4197 | 259898 | return m_rocksdb_tx->GetIterator(options, column_family); | |
| 4198 | } | ||
| 4199 | |||
| 4200 | 240 | const rocksdb::Transaction *get_rdb_trx() const { return m_rocksdb_tx; } | |
| 4201 | |||
| 4202 | 116107992 | bool is_tx_started() const override { return (m_rocksdb_tx != nullptr); } | |
| 4203 | |||
| 4204 | 3580990 | void start_tx() override { | |
| 4205 | 3580990 | rocksdb::TransactionOptions tx_opts; | |
| 4206 | 3580990 | rocksdb::WriteOptions write_opts; | |
| 4207 | 3580985 | tx_opts.set_snapshot = false; | |
| 4208 |
1/2✓ Branch 0 taken 3581116 times.
✗ Branch 1 not taken.
|
3580985 | tx_opts.lock_timeout = rdb_convert_sec_to_ms(m_timeout_sec); |
| 4209 |
1/2✓ Branch 0 taken 3581254 times.
✗ Branch 1 not taken.
|
3581116 | tx_opts.deadlock_detect = THDVAR(m_thd, deadlock_detect); |
| 4210 |
1/2✓ Branch 0 taken 3581308 times.
✗ Branch 1 not taken.
|
3581254 | tx_opts.deadlock_detect_depth = THDVAR(m_thd, deadlock_detect_depth); |
| 4211 | // If this variable is set, this will write commit time write batch | ||
| 4212 | // information on recovery or memtable flush. | ||
| 4213 | 3581383 | tx_opts.use_only_the_last_commit_time_batch_for_recovery = | |
| 4214 |
1/2✓ Branch 0 taken 3581383 times.
✗ Branch 1 not taken.
|
3581308 | THDVAR(m_thd, commit_time_batch_for_recovery); |
| 4215 |
1/2✓ Branch 0 taken 3581212 times.
✗ Branch 1 not taken.
|
3581383 | tx_opts.max_write_batch_size = THDVAR(m_thd, write_batch_max_bytes); |
| 4216 | 3581221 | tx_opts.write_batch_flush_threshold = | |
| 4217 |
1/2✓ Branch 0 taken 3581221 times.
✗ Branch 1 not taken.
|
3581212 | THDVAR(m_thd, write_batch_flush_threshold); |
| 4218 | |||
| 4219 |
2/2✓ Branch 0 taken 3470010 times.
✓ Branch 1 taken 111211 times.
|
7051079 | write_opts.sync = (rocksdb_flush_log_at_trx_commit == FLUSH_LOG_SYNC) && |
| 4220 |
2/4✓ Branch 0 taken 3469858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3469971 times.
✗ Branch 3 not taken.
|
3470010 | rdb_sync_wal_supported(); |
| 4221 |
1/2✓ Branch 0 taken 3581032 times.
✗ Branch 1 not taken.
|
3581069 | fix_write_disable_wal_value(m_thd, write_opts.sync); |
| 4222 |
1/2✓ Branch 0 taken 3581244 times.
✗ Branch 1 not taken.
|
3581032 | write_opts.disableWAL = THDVAR(m_thd, write_disable_wal); |
| 4223 | 3581296 | write_opts.ignore_missing_column_families = | |
| 4224 |
1/2✓ Branch 0 taken 3581296 times.
✗ Branch 1 not taken.
|
3581244 | THDVAR(m_thd, write_ignore_missing_column_families); |
| 4225 | |||
| 4226 | /* | ||
| 4227 | If m_rocksdb_reuse_tx is null this will create a new transaction object. | ||
| 4228 | Otherwise it will reuse the existing one. | ||
| 4229 | */ | ||
| 4230 | 3580820 | m_rocksdb_tx = | |
| 4231 |
1/2✓ Branch 0 taken 3580820 times.
✗ Branch 1 not taken.
|
3581296 | rdb->BeginTransaction(write_opts, tx_opts, m_rocksdb_reuse_tx); |
| 4232 | 3580820 | m_rocksdb_reuse_tx = nullptr; | |
| 4233 | |||
| 4234 |
1/2✓ Branch 0 taken 3580696 times.
✗ Branch 1 not taken.
|
3580820 | m_read_opts = rocksdb::ReadOptions(); |
| 4235 | |||
| 4236 |
1/2✓ Branch 0 taken 3580759 times.
✗ Branch 1 not taken.
|
3581287 | set_initial_savepoint(); |
| 4237 | |||
| 4238 | 3580759 | m_ddl_transaction = false; | |
| 4239 | 3580759 | m_is_delayed_snapshot = false; | |
| 4240 | 3580759 | } | |
| 4241 | |||
| 4242 | 3613523 | void set_name() override { | |
| 4243 | 3613523 | XID xid; | |
| 4244 |
1/2✓ Branch 0 taken 3613620 times.
✗ Branch 1 not taken.
|
3613403 | thd_get_xid(m_thd, reinterpret_cast<MYSQL_XID *>(&xid)); |
| 4245 |
1/2✓ Branch 0 taken 3613622 times.
✗ Branch 1 not taken.
|
3613620 | auto name = m_rocksdb_tx->GetName(); |
| 4246 |
2/2✓ Branch 0 taken 132382 times.
✓ Branch 1 taken 3481129 times.
|
3613622 | if (!name.empty()) { |
| 4247 |
2/4✓ Branch 0 taken 132382 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 132382 times.
|
132382 | assert(name == rdb_xid_to_string(xid)); |
| 4248 | 132382 | return; | |
| 4249 | } | ||
| 4250 |
2/4✓ Branch 0 taken 3481170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3481734 times.
✗ Branch 3 not taken.
|
3481129 | rocksdb::Status s = m_rocksdb_tx->SetName(rdb_xid_to_string(xid)); |
| 4251 |
2/4✓ Branch 0 taken 3481751 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3481751 times.
|
3481751 | assert(s.ok()); |
| 4252 |
2/4✓ Branch 0 taken 3481751 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3481751 times.
|
3481751 | if (!s.ok()) { |
| 4253 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_TX_COMMIT); | |
| 4254 | } | ||
| 4255 |
2/2✓ Branch 0 taken 3481751 times.
✓ Branch 1 taken 132382 times.
|
3614133 | } |
| 4256 | |||
| 4257 | /* Implementations of do_*savepoint based on rocksdB::Transaction savepoints | ||
| 4258 | */ | ||
| 4259 | 3630175 | void do_set_savepoint() override { m_rocksdb_tx->SetSavePoint(); } | |
| 4260 | 98892 | rocksdb::Status do_pop_savepoint() override { | |
| 4261 | 98892 | return m_rocksdb_tx->PopSavePoint(); | |
| 4262 | } | ||
| 4263 | |||
| 4264 | 138 | void do_rollback_to_savepoint() override { | |
| 4265 | 138 | m_rocksdb_tx->RollbackToSavePoint(); | |
| 4266 | 138 | } | |
| 4267 | |||
| 4268 | /* | ||
| 4269 | Start a statement inside a multi-statement transaction. | ||
| 4270 | |||
| 4271 | @todo: are we sure this is called once (and not several times) per | ||
| 4272 | statement start? | ||
| 4273 | |||
| 4274 | For hooking to start of statement that is its own transaction, see | ||
| 4275 | ha_rocksdb::external_lock(). | ||
| 4276 | */ | ||
| 4277 | 417920 | void start_stmt() override { | |
| 4278 | // Set the snapshot to delayed acquisition (SetSnapshotOnNextOperation) | ||
| 4279 | 417920 | acquire_snapshot(false); | |
| 4280 | 417920 | } | |
| 4281 | |||
| 4282 | /* | ||
| 4283 | This must be called when last statement is rolled back, but the transaction | ||
| 4284 | continues | ||
| 4285 | */ | ||
| 4286 | 3458 | void rollback_stmt() override { | |
| 4287 | /* TODO: here we must release the locks taken since the start_stmt() call */ | ||
| 4288 |
2/2✓ Branch 0 taken 3386 times.
✓ Branch 1 taken 72 times.
|
3458 | if (m_rocksdb_tx) { |
| 4289 | 3386 | const rocksdb::Snapshot *const org_snapshot = m_rocksdb_tx->GetSnapshot(); | |
| 4290 | 3386 | rollback_to_stmt_savepoint(); | |
| 4291 | |||
| 4292 | 3386 | const rocksdb::Snapshot *const cur_snapshot = m_rocksdb_tx->GetSnapshot(); | |
| 4293 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 3258 times.
|
3386 | if (org_snapshot != cur_snapshot) { |
| 4294 |
1/2✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
|
128 | if (org_snapshot != nullptr) m_snapshot_timestamp = 0; |
| 4295 | |||
| 4296 | 128 | m_read_opts.snapshot = cur_snapshot; | |
| 4297 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 112 times.
|
128 | if (cur_snapshot != nullptr) { |
| 4298 | 16 | rdb->GetEnv()->GetCurrentTime(&m_snapshot_timestamp); | |
| 4299 | } else { | ||
| 4300 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | m_rocksdb_tx->SetSnapshotOnNextOperation(m_notifier); |
| 4301 | 112 | m_is_delayed_snapshot = true; | |
| 4302 | } | ||
| 4303 | } | ||
| 4304 | } | ||
| 4305 | 3458 | } | |
| 4306 | |||
| 4307 | 2569 | explicit Rdb_transaction_impl(THD *const thd) | |
| 4308 | 2569 | : Rdb_transaction(thd), m_rocksdb_tx(nullptr) { | |
| 4309 | // Create a notifier that can be called when a snapshot gets generated. | ||
| 4310 |
1/2✓ Branch 0 taken 2568 times.
✗ Branch 1 not taken.
|
2568 | m_notifier = std::make_shared<Rdb_snapshot_notifier>(this); |
| 4311 | 2565 | } | |
| 4312 | |||
| 4313 | 10100 | virtual ~Rdb_transaction_impl() override { | |
| 4314 | // Remove from the global list before all other processing is started. | ||
| 4315 | // Otherwise, information_schema.rocksdb_trx can crash on this object. | ||
| 4316 | 5050 | Rdb_transaction::remove_from_global_trx_list(); | |
| 4317 | |||
| 4318 | 5054 | rollback(); | |
| 4319 | |||
| 4320 | // Theoretically the notifier could outlive the Rdb_transaction_impl | ||
| 4321 | // (because of the shared_ptr), so let it know it can't reference | ||
| 4322 | // the transaction anymore. | ||
| 4323 | 5054 | m_notifier->detach(); | |
| 4324 | |||
| 4325 | // Free any transaction memory that is still hanging around. | ||
| 4326 |
1/2✓ Branch 0 taken 2527 times.
✗ Branch 1 not taken.
|
5054 | delete m_rocksdb_reuse_tx; |
| 4327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2527 times.
|
5054 | assert(m_rocksdb_tx == nullptr); |
| 4328 | 10104 | } | |
| 4329 | }; | ||
| 4330 | |||
| 4331 | /* This is a rocksdb write batch. This class doesn't hold or wait on any | ||
| 4332 | transaction locks (skips rocksdb transaction API) thus giving better | ||
| 4333 | performance. | ||
| 4334 | |||
| 4335 | Currently this is only used for replication threads which are guaranteed | ||
| 4336 | to be non-conflicting. Any further usage of this class should completely | ||
| 4337 | be thought thoroughly. | ||
| 4338 | */ | ||
| 4339 | class Rdb_writebatch_impl : public Rdb_transaction { | ||
| 4340 | rocksdb::WriteBatchWithIndex *m_batch; | ||
| 4341 | rocksdb::WriteOptions write_opts; | ||
| 4342 | // Called after commit/rollback. | ||
| 4343 | 6024 | void reset() { | |
| 4344 | 6024 | m_batch->Clear(); | |
| 4345 | 6024 | m_read_opts = rocksdb::ReadOptions(); | |
| 4346 | 6024 | m_ddl_transaction = false; | |
| 4347 | 6024 | } | |
| 4348 | |||
| 4349 | private: | ||
| 4350 | 6002 | bool prepare() override { return true; } | |
| 4351 | |||
| 4352 | 6002 | bool commit_no_binlog() override { | |
| 4353 | 6002 | bool res = false; | |
| 4354 | 6002 | rocksdb::Status s; | |
| 4355 | 6002 | rocksdb::TransactionDBWriteOptimizations optimize; | |
| 4356 | 6002 | optimize.skip_concurrency_control = true; | |
| 4357 | |||
| 4358 |
2/4✓ Branch 0 taken 6002 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6002 times.
✗ Branch 3 not taken.
|
6002 | s = merge_auto_incr_map(m_batch->GetWriteBatch()); |
| 4359 |
2/4✓ Branch 0 taken 6002 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6002 times.
|
6002 | if (!s.ok()) { |
| 4360 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_TX_COMMIT); | |
| 4361 | ✗ | res = true; | |
| 4362 | ✗ | goto error; | |
| 4363 | } | ||
| 4364 | |||
| 4365 |
1/2✓ Branch 0 taken 6002 times.
✗ Branch 1 not taken.
|
6002 | release_snapshot(); |
| 4366 | |||
| 4367 |
2/4✓ Branch 0 taken 6002 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6002 times.
✗ Branch 3 not taken.
|
6002 | s = rdb->Write(write_opts, optimize, m_batch->GetWriteBatch()); |
| 4368 |
2/4✓ Branch 0 taken 6002 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6002 times.
|
6002 | if (!s.ok()) { |
| 4369 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_TX_COMMIT); | |
| 4370 | ✗ | res = true; | |
| 4371 | ✗ | goto error; | |
| 4372 | } | ||
| 4373 | 6002 | on_commit(); | |
| 4374 | 6002 | error: | |
| 4375 | 6002 | on_rollback(); | |
| 4376 |
1/2✓ Branch 0 taken 6002 times.
✗ Branch 1 not taken.
|
6002 | reset(); |
| 4377 | |||
| 4378 | 6002 | m_write_count = 0; | |
| 4379 | 6002 | set_tx_read_only(false); | |
| 4380 | 6002 | m_rollback_only = false; | |
| 4381 | 6002 | return res; | |
| 4382 | 6002 | } | |
| 4383 | |||
| 4384 | /* Implementations of do_*savepoint based on rocksdB::WriteBatch savepoints */ | ||
| 4385 | 20 | void do_set_savepoint() override { m_batch->SetSavePoint(); } | |
| 4386 | 20 | rocksdb::Status do_pop_savepoint() override { | |
| 4387 | 20 | return m_batch->PopSavePoint(); | |
| 4388 | } | ||
| 4389 | |||
| 4390 | ✗ | void do_rollback_to_savepoint() override { m_batch->RollbackToSavePoint(); } | |
| 4391 | |||
| 4392 | public: | ||
| 4393 | 6 | bool is_writebatch_trx() const override { return true; } | |
| 4394 | |||
| 4395 | 18026 | void set_lock_timeout(int timeout_sec_arg) override { | |
| 4396 | // Nothing to do here. | ||
| 4397 | 18026 | } | |
| 4398 | |||
| 4399 | 6002 | void set_sync(bool sync) override { write_opts.sync = sync; } | |
| 4400 | |||
| 4401 | ✗ | void release_lock(const Rdb_key_def &key_descr, const std::string &rowkey, | |
| 4402 | bool force) override { | ||
| 4403 | // Nothing to do here since we don't hold any row locks. | ||
| 4404 | } | ||
| 4405 | |||
| 4406 | 12 | void rollback() override { | |
| 4407 | 12 | on_rollback(); | |
| 4408 | 12 | m_write_count = 0; | |
| 4409 | 12 | m_row_lock_count = 0; | |
| 4410 | 12 | release_snapshot(); | |
| 4411 | |||
| 4412 | 12 | reset(); | |
| 4413 | 12 | set_tx_read_only(false); | |
| 4414 | 12 | m_rollback_only = false; | |
| 4415 | 12 | } | |
| 4416 | |||
| 4417 | 6010 | void acquire_snapshot(bool acquire_now) override { | |
| 4418 |
2/2✓ Branch 0 taken 6004 times.
✓ Branch 1 taken 6 times.
|
6010 | if (m_read_opts.snapshot == nullptr) snapshot_created(rdb->GetSnapshot()); |
| 4419 | 6010 | } | |
| 4420 | |||
| 4421 | 18014 | void release_snapshot() override { | |
| 4422 |
2/2✓ Branch 0 taken 6004 times.
✓ Branch 1 taken 12010 times.
|
18014 | if (m_read_opts.snapshot != nullptr) { |
| 4423 | 6004 | rdb->ReleaseSnapshot(m_read_opts.snapshot); | |
| 4424 | 6004 | m_read_opts.snapshot = nullptr; | |
| 4425 | } | ||
| 4426 | 18014 | } | |
| 4427 | |||
| 4428 | 6010 | rocksdb::Status put(rocksdb::ColumnFamilyHandle *const column_family, | |
| 4429 | const rocksdb::Slice &key, const rocksdb::Slice &value, | ||
| 4430 | const bool assume_tracked) override { | ||
| 4431 | 6010 | ++m_write_count; | |
| 4432 | 6010 | m_batch->Put(column_family, key, value); | |
| 4433 | // Note Put/Delete in write batch doesn't return any error code. We simply | ||
| 4434 | // return OK here. | ||
| 4435 | 6010 | return rocksdb::Status::OK(); | |
| 4436 | } | ||
| 4437 | |||
| 4438 | ✗ | rocksdb::Status delete_key(rocksdb::ColumnFamilyHandle *const column_family, | |
| 4439 | const rocksdb::Slice &key, | ||
| 4440 | const bool assume_tracked) override { | ||
| 4441 | ✗ | ++m_write_count; | |
| 4442 | ✗ | m_batch->Delete(column_family, key); | |
| 4443 | ✗ | return rocksdb::Status::OK(); | |
| 4444 | } | ||
| 4445 | |||
| 4446 | ✗ | rocksdb::Status single_delete( | |
| 4447 | rocksdb::ColumnFamilyHandle *const column_family, | ||
| 4448 | const rocksdb::Slice &key, const bool assume_tracked) override { | ||
| 4449 | ✗ | ++m_write_count; | |
| 4450 | ✗ | m_batch->SingleDelete(column_family, key); | |
| 4451 | ✗ | return rocksdb::Status::OK(); | |
| 4452 | } | ||
| 4453 | |||
| 4454 | ✗ | bool has_modifications() const override { | |
| 4455 | ✗ | return m_batch->GetWriteBatch()->Count() > 0; | |
| 4456 | } | ||
| 4457 | |||
| 4458 | ✗ | rocksdb::WriteBatchBase *get_write_batch() override { return m_batch; } | |
| 4459 | |||
| 4460 | 3000 | rocksdb::WriteBatchBase *get_indexed_write_batch() override { | |
| 4461 | 3000 | ++m_write_count; | |
| 4462 | 3000 | return m_batch; | |
| 4463 | } | ||
| 4464 | |||
| 4465 | 9010 | rocksdb::Status get(rocksdb::ColumnFamilyHandle *const column_family, | |
| 4466 | const rocksdb::Slice &key, | ||
| 4467 | rocksdb::PinnableSlice *const value) const override { | ||
| 4468 | 9010 | value->Reset(); | |
| 4469 | 9010 | return m_batch->GetFromBatchAndDB(rdb, m_read_opts, column_family, key, | |
| 4470 | 9010 | value); | |
| 4471 | } | ||
| 4472 | |||
| 4473 | 9010 | rocksdb::Status get_for_update(const Rdb_key_def &key_descr, | |
| 4474 | const rocksdb::Slice &key, | ||
| 4475 | rocksdb::PinnableSlice *const value, | ||
| 4476 | bool /* exclusive */, | ||
| 4477 | const bool /* do_validate */, | ||
| 4478 | bool /* no_wait */) override { | ||
| 4479 | 9010 | rocksdb::ColumnFamilyHandle *const column_family = key_descr.get_cf(); | |
| 4480 |
2/2✓ Branch 0 taken 3000 times.
✓ Branch 1 taken 6010 times.
|
9010 | if (value == nullptr) { |
| 4481 |
1/2✓ Branch 0 taken 3000 times.
✗ Branch 1 not taken.
|
3000 | rocksdb::PinnableSlice pin_val; |
| 4482 |
1/2✓ Branch 0 taken 3000 times.
✗ Branch 1 not taken.
|
3000 | rocksdb::Status s = get(column_family, key, &pin_val); |
| 4483 |
1/2✓ Branch 0 taken 3000 times.
✗ Branch 1 not taken.
|
3000 | pin_val.Reset(); |
| 4484 | 3000 | return s; | |
| 4485 | 3000 | } | |
| 4486 | |||
| 4487 | 6010 | return get(column_family, key, value); | |
| 4488 | } | ||
| 4489 | |||
| 4490 | 3000 | rocksdb::Iterator *get_iterator( | |
| 4491 | const rocksdb::ReadOptions &options, | ||
| 4492 | rocksdb::ColumnFamilyHandle *const column_family) override { | ||
| 4493 | 3000 | const auto it = rdb->NewIterator(options); | |
| 4494 | 3000 | return m_batch->NewIteratorWithBase(it); | |
| 4495 | } | ||
| 4496 | |||
| 4497 | 30022 | bool is_tx_started() const override { return (m_batch != nullptr); } | |
| 4498 | |||
| 4499 | 10 | void start_tx() override { | |
| 4500 | 10 | reset(); | |
| 4501 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
20 | write_opts.sync = (rocksdb_flush_log_at_trx_commit == FLUSH_LOG_SYNC) && |
| 4502 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | rdb_sync_wal_supported(); |
| 4503 | |||
| 4504 | 10 | fix_write_disable_wal_value(m_thd, write_opts.sync); | |
| 4505 | 10 | write_opts.disableWAL = THDVAR(m_thd, write_disable_wal); | |
| 4506 | 10 | write_opts.ignore_missing_column_families = | |
| 4507 | 10 | THDVAR(m_thd, write_ignore_missing_column_families); | |
| 4508 | |||
| 4509 | 10 | set_initial_savepoint(); | |
| 4510 | 10 | } | |
| 4511 | |||
| 4512 | 6002 | void set_name() override {} | |
| 4513 | |||
| 4514 | 6006 | void start_stmt() override {} | |
| 4515 | |||
| 4516 | ✗ | void rollback_stmt() override { | |
| 4517 | ✗ | if (m_batch) rollback_to_stmt_savepoint(); | |
| 4518 | } | ||
| 4519 | |||
| 4520 | 10 | explicit Rdb_writebatch_impl(THD *const thd) | |
| 4521 | 10 | : Rdb_transaction(thd), m_batch(nullptr) { | |
| 4522 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | m_batch = new rocksdb::WriteBatchWithIndex(rocksdb::BytewiseComparator(), 0, |
| 4523 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | true); |
| 4524 | 10 | } | |
| 4525 | |||
| 4526 | 40 | virtual ~Rdb_writebatch_impl() override { | |
| 4527 | // Remove from the global list before all other processing is started. | ||
| 4528 | // Otherwise, information_schema.rocksdb_trx can crash on this object. | ||
| 4529 | 20 | Rdb_transaction::remove_from_global_trx_list(); | |
| 4530 | |||
| 4531 | 20 | rollback(); | |
| 4532 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
20 | delete m_batch; |
| 4533 | 40 | } | |
| 4534 | }; | ||
| 4535 | |||
| 4536 | 3306638 | void Rdb_snapshot_notifier::SnapshotCreated( | |
| 4537 | const rocksdb::Snapshot *const snapshot) { | ||
| 4538 |
1/2✓ Branch 0 taken 3306653 times.
✗ Branch 1 not taken.
|
3306638 | if (m_owning_tx != nullptr) { |
| 4539 | 3306653 | m_owning_tx->snapshot_created(snapshot); | |
| 4540 | } | ||
| 4541 | 3306732 | } | |
| 4542 | |||
| 4543 | std::multiset<Rdb_transaction *> Rdb_transaction::s_tx_list; | ||
| 4544 | Rds_mysql_mutex Rdb_transaction::s_tx_list_mutex; | ||
| 4545 | |||
| 4546 | class Rdb_ha_data { | ||
| 4547 | public: | ||
| 4548 | 2590 | Rdb_ha_data() | |
| 4549 | 2590 | : checkpoint_dir(nullptr), trx(nullptr), disable_file_deletions(false) {} | |
| 4550 | |||
| 4551 | 2541 | ~Rdb_ha_data() { clear_checkpoint_dir(); } | |
| 4552 | |||
| 4553 | 2548 | const char *get_checkpoint_dir() const { return checkpoint_dir; } | |
| 4554 | |||
| 4555 | 6 | void set_checkpoint_dir(const char *checkpoint_dir_) { | |
| 4556 | 6 | clear_checkpoint_dir(); | |
| 4557 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (checkpoint_dir_ != nullptr) { |
| 4558 | 3 | checkpoint_dir = strdup(checkpoint_dir_); | |
| 4559 | } | ||
| 4560 | 6 | } | |
| 4561 | |||
| 4562 | 335596922 | Rdb_transaction *get_trx() const { return trx; } | |
| 4563 | |||
| 4564 | 5110 | void set_trx(Rdb_transaction *t) { trx = t; } | |
| 4565 | |||
| 4566 | 2557 | bool get_disable_file_deletions() const { return disable_file_deletions; } | |
| 4567 | |||
| 4568 | 11 | void set_disable_file_deletions(bool d) { disable_file_deletions = d; } | |
| 4569 | |||
| 4570 | private: | ||
| 4571 | 2548 | void clear_checkpoint_dir() { | |
| 4572 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2545 times.
|
2548 | if (checkpoint_dir) { |
| 4573 | 3 | free(checkpoint_dir); | |
| 4574 | 3 | checkpoint_dir = nullptr; | |
| 4575 | } | ||
| 4576 | 2548 | } | |
| 4577 | |||
| 4578 | private: | ||
| 4579 | char *checkpoint_dir; | ||
| 4580 | Rdb_transaction *trx; | ||
| 4581 | bool disable_file_deletions; | ||
| 4582 | }; | ||
| 4583 | |||
| 4584 | 335400764 | static Rdb_ha_data *&get_ha_data(THD *const thd) { | |
| 4585 | Rdb_ha_data **ha_data = | ||
| 4586 | 335400764 | reinterpret_cast<Rdb_ha_data **>(my_core::thd_ha_data(thd, rocksdb_hton)); | |
| 4587 |
2/2✓ Branch 0 taken 2590 times.
✓ Branch 1 taken 335623486 times.
|
335626076 | if (*ha_data == nullptr) { |
| 4588 | 2590 | *ha_data = new Rdb_ha_data(); | |
| 4589 | } | ||
| 4590 | 335587704 | return *ha_data; | |
| 4591 | } | ||
| 4592 | |||
| 4593 | 2543 | static void destroy_ha_data(THD *const thd) { | |
| 4594 | 2543 | Rdb_ha_data *&ha_data = get_ha_data(thd); | |
| 4595 |
1/2✓ Branch 0 taken 2548 times.
✗ Branch 1 not taken.
|
2548 | delete ha_data; |
| 4596 | 2547 | ha_data = nullptr; | |
| 4597 | 2547 | } | |
| 4598 | |||
| 4599 | 335379979 | Rdb_transaction *get_tx_from_thd(THD *const thd) { | |
| 4600 | 335379979 | return get_ha_data(thd)->get_trx(); | |
| 4601 | } | ||
| 4602 | |||
| 4603 | 5108 | static void set_tx_on_thd(THD *const thd, Rdb_transaction *trx) { | |
| 4604 | 5108 | return get_ha_data(thd)->set_trx(trx); | |
| 4605 | } | ||
| 4606 | |||
| 4607 | class Rdb_perf_context_guard { | ||
| 4608 | Rdb_io_perf m_io_perf; | ||
| 4609 | Rdb_io_perf *m_io_perf_ptr; | ||
| 4610 | Rdb_transaction *m_tx; | ||
| 4611 | uint m_level; | ||
| 4612 | |||
| 4613 | public: | ||
| 4614 | Rdb_perf_context_guard(const Rdb_perf_context_guard &) = delete; | ||
| 4615 | Rdb_perf_context_guard &operator=(const Rdb_perf_context_guard &) = delete; | ||
| 4616 | |||
| 4617 | 24016 | explicit Rdb_perf_context_guard(Rdb_io_perf *io_perf, uint level) | |
| 4618 | 24016 | : m_io_perf_ptr(io_perf), m_tx(nullptr), m_level(level) { | |
| 4619 | 24016 | m_io_perf_ptr->start(m_level); | |
| 4620 | 24016 | } | |
| 4621 | |||
| 4622 | 4008331 | explicit Rdb_perf_context_guard(Rdb_transaction *tx, uint level) | |
| 4623 | 4008331 | : m_io_perf_ptr(nullptr), m_tx(tx), m_level(level) { | |
| 4624 | /* | ||
| 4625 | if perf_context information is already being recorded, this becomes a | ||
| 4626 | no-op | ||
| 4627 | */ | ||
| 4628 |
1/2✓ Branch 0 taken 4008331 times.
✗ Branch 1 not taken.
|
4008331 | if (tx != nullptr) { |
| 4629 | 4008331 | tx->io_perf_start(&m_io_perf); | |
| 4630 | } | ||
| 4631 | 4008331 | } | |
| 4632 | |||
| 4633 | 4032347 | ~Rdb_perf_context_guard() { | |
| 4634 |
2/2✓ Branch 0 taken 4008331 times.
✓ Branch 1 taken 24016 times.
|
4032347 | if (m_tx != nullptr) { |
| 4635 | 4008331 | m_tx->io_perf_end_and_record(); | |
| 4636 |
1/2✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
|
24016 | } else if (m_io_perf_ptr != nullptr) { |
| 4637 | 24016 | m_io_perf_ptr->end_and_record(m_level); | |
| 4638 | } | ||
| 4639 | 4032347 | } | |
| 4640 | }; | ||
| 4641 | |||
| 4642 | /* | ||
| 4643 | TODO: maybe, call this in external_lock() and store in ha_rocksdb.. | ||
| 4644 | */ | ||
| 4645 | |||
| 4646 | 112236955 | static Rdb_transaction *get_or_create_tx(THD *const thd) { | |
| 4647 | 112236955 | Rdb_transaction *tx = get_tx_from_thd(thd); | |
| 4648 | // TODO: this is called too many times.. O(#rows) | ||
| 4649 |
2/2✓ Branch 0 taken 2579 times.
✓ Branch 1 taken 112375043 times.
|
112377622 | if (tx == nullptr) { |
| 4650 |
6/6✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2568 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 2569 times.
|
5148 | if ((rpl_skip_tx_api_var && thd->rli_slave) || |
| 4651 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2569 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2569 | (THDVAR(thd, master_skip_tx_api) && !thd->rli_slave)) { |
| 4652 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | tx = new Rdb_writebatch_impl(thd); |
| 4653 | } else { | ||
| 4654 |
1/2✓ Branch 0 taken 2567 times.
✗ Branch 1 not taken.
|
2569 | tx = new Rdb_transaction_impl(thd); |
| 4655 | } | ||
| 4656 | 2577 | tx->set_params(THDVAR(thd, lock_wait_timeout), rocksdb_max_row_locks); | |
| 4657 | 2576 | tx->start_tx(); | |
| 4658 | 2576 | set_tx_on_thd(thd, tx); | |
| 4659 | |||
| 4660 | // Add the transaction to the global list of transactions | ||
| 4661 | // once it is fully constructed. | ||
| 4662 | 2578 | tx->add_to_global_trx_list(); | |
| 4663 | } else { | ||
| 4664 | 112375043 | tx->set_params(THDVAR(thd, lock_wait_timeout), rocksdb_max_row_locks); | |
| 4665 |
2/2✓ Branch 0 taken 3577981 times.
✓ Branch 1 taken 108716128 times.
|
112300426 | if (!tx->is_tx_started()) { |
| 4666 | 3577981 | tx->start_tx(); | |
| 4667 | } | ||
| 4668 | } | ||
| 4669 | |||
| 4670 | 112299768 | return tx; | |
| 4671 | } | ||
| 4672 | |||
| 4673 | 2547 | static int rocksdb_close_connection(handlerton *const hton, THD *const thd) { | |
| 4674 | 2547 | Rdb_transaction *tx = get_tx_from_thd(thd); | |
| 4675 |
2/2✓ Branch 0 taken 2537 times.
✓ Branch 1 taken 11 times.
|
2548 | if (tx != nullptr) { |
| 4676 | bool is_critical_error; | ||
| 4677 |
1/2✓ Branch 0 taken 2535 times.
✗ Branch 1 not taken.
|
2537 | int rc = tx->finish_bulk_load(&is_critical_error, false); |
| 4678 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2532 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
2535 | if (rc != 0 && is_critical_error) { |
| 4679 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 4680 | "Error %d finalizing last SST file while disconnecting", | ||
| 4681 | rc); | ||
| 4682 | } | ||
| 4683 | |||
| 4684 |
1/2✓ Branch 0 taken 2535 times.
✗ Branch 1 not taken.
|
2535 | delete tx; |
| 4685 |
1/2✓ Branch 0 taken 2534 times.
✗ Branch 1 not taken.
|
2534 | set_tx_on_thd(thd, nullptr); |
| 4686 | } | ||
| 4687 | 2545 | const char *checkpoint_dir = get_ha_data(thd)->get_checkpoint_dir(); | |
| 4688 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2541 times.
|
2543 | if (checkpoint_dir != nullptr) { |
| 4689 | 2 | rocksdb_remove_checkpoint(checkpoint_dir); | |
| 4690 | 2 | get_ha_data(thd)->set_checkpoint_dir(nullptr); | |
| 4691 | } | ||
| 4692 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2540 times.
|
2543 | if (get_ha_data(thd)->get_disable_file_deletions()) { |
| 4693 | 3 | rdb->EnableFileDeletions(false); | |
| 4694 | } | ||
| 4695 | 2543 | destroy_ha_data(thd); | |
| 4696 | 2548 | return HA_EXIT_SUCCESS; | |
| 4697 | } | ||
| 4698 | |||
| 4699 | 6 | static int rocksdb_create_temporary_checkpoint_validate( | |
| 4700 | my_core::THD *const thd, my_core::SYS_VAR *const /* unused */, | ||
| 4701 | void *const save, my_core::st_mysql_value *const value) { | ||
| 4702 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(rdb != nullptr); |
| 4703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(thd != nullptr); |
| 4704 | |||
| 4705 | char buf[FN_REFLEN]; | ||
| 4706 | 6 | int len = sizeof(buf); | |
| 4707 | |||
| 4708 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | const char *current_checkpoint_dir = get_ha_data(thd)->get_checkpoint_dir(); |
| 4709 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | const char *new_checkpoint_dir = value->val_str(value, buf, &len); |
| 4710 | |||
| 4711 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
6 | if (current_checkpoint_dir != nullptr && new_checkpoint_dir != nullptr) { |
| 4712 | 1 | *reinterpret_cast<const char **>(save) = current_checkpoint_dir; | |
| 4713 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error( |
| 4714 | ER_GET_ERRMSG, MYF(0), HA_ERR_ROCKSDB_STATUS_INVALID_ARGUMENT, | ||
| 4715 | "Invalid argument: Temporary checkpoint already exists for session", | ||
| 4716 | rocksdb_hton_name); | ||
| 4717 | 1 | return HA_EXIT_FAILURE; | |
| 4718 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | } else if (new_checkpoint_dir != nullptr) { |
| 4719 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | const auto res = rocksdb_create_checkpoint(new_checkpoint_dir); |
| 4720 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if (res == HA_EXIT_SUCCESS) { |
| 4721 | 3 | *reinterpret_cast<const char **>(save) = new_checkpoint_dir; | |
| 4722 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | get_ha_data(thd)->set_checkpoint_dir(new_checkpoint_dir); |
| 4723 | } else { | ||
| 4724 | 1 | return res; | |
| 4725 | } | ||
| 4726 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | } else if (current_checkpoint_dir != nullptr) { |
| 4727 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | const auto res = rocksdb_remove_checkpoint(current_checkpoint_dir); |
| 4728 | 1 | *reinterpret_cast<const char **>(save) = nullptr; | |
| 4729 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | get_ha_data(thd)->set_checkpoint_dir(nullptr); |
| 4730 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (res != HA_EXIT_SUCCESS) { |
| 4731 | ✗ | return res; | |
| 4732 | } | ||
| 4733 | } else { | ||
| 4734 | ✗ | *reinterpret_cast<const char **>(save) = nullptr; | |
| 4735 | ✗ | get_ha_data(thd)->set_checkpoint_dir(nullptr); | |
| 4736 | } | ||
| 4737 | 4 | return HA_EXIT_SUCCESS; | |
| 4738 | } | ||
| 4739 | |||
| 4740 | 15 | static void rocksdb_disable_file_deletions_update( | |
| 4741 | my_core::THD *const thd, my_core::SYS_VAR *const /* unused */, | ||
| 4742 | void *const var_ptr, const void *const save) { | ||
| 4743 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(rdb != nullptr); |
| 4744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(thd != nullptr); |
| 4745 | |||
| 4746 | 15 | bool val = *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 4747 |
6/6✓ Branch 0 taken 9 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 8 times.
|
15 | if (val && !get_ha_data(thd)->get_disable_file_deletions()) { |
| 4748 | 7 | rdb->DisableFileDeletions(); | |
| 4749 | 7 | get_ha_data(thd)->set_disable_file_deletions(true); | |
| 4750 |
6/6✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
|
8 | } else if (!val && get_ha_data(thd)->get_disable_file_deletions()) { |
| 4751 | 4 | rdb->EnableFileDeletions(false); | |
| 4752 | 4 | get_ha_data(thd)->set_disable_file_deletions(false); | |
| 4753 | } | ||
| 4754 | 15 | } | |
| 4755 | |||
| 4756 | /** | ||
| 4757 | Called by hton->flush_logs after MySQL group commit prepares a set of | ||
| 4758 | transactions. | ||
| 4759 | */ | ||
| 4760 | 3460233 | static bool rocksdb_flush_wal(handlerton *const hton MY_ATTRIBUTE((__unused__)), | |
| 4761 | bool binlog_group_flush) { | ||
| 4762 |
1/2✓ Branch 0 taken 3460233 times.
✗ Branch 1 not taken.
|
3460233 | DBUG_ENTER("rocksdb_flush_wal"); |
| 4763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3460233 times.
|
3460233 | assert(rdb != nullptr); |
| 4764 | |||
| 4765 | /** | ||
| 4766 | If !binlog_group_flush, we got invoked by FLUSH LOGS or similar. | ||
| 4767 | Else, we got invoked by binlog group commit during flush stage. | ||
| 4768 | */ | ||
| 4769 | |||
| 4770 |
2/2✓ Branch 0 taken 3454473 times.
✓ Branch 1 taken 5760 times.
|
3460233 | if (binlog_group_flush && |
| 4771 |
2/2✓ Branch 0 taken 93137 times.
✓ Branch 1 taken 3361336 times.
|
3454473 | rocksdb_flush_log_at_trx_commit == FLUSH_LOG_NEVER) { |
| 4772 | /** | ||
| 4773 | rocksdb_flush_log_at_trx_commit=0 | ||
| 4774 | (write and sync based on timer in Rdb_background_thread). | ||
| 4775 | Do not flush the redo log during binlog group commit. | ||
| 4776 | */ | ||
| 4777 |
1/2✓ Branch 0 taken 93137 times.
✗ Branch 1 not taken.
|
93137 | DBUG_RETURN(false); |
| 4778 | } | ||
| 4779 | |||
| 4780 |
4/6✓ Branch 0 taken 3361336 times.
✓ Branch 1 taken 5760 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3361336 times.
✓ Branch 4 taken 3367096 times.
✗ Branch 5 not taken.
|
3367096 | if (!binlog_group_flush || !rocksdb_db_options->allow_mmap_writes || |
| 4781 | ✗ | rocksdb_flush_log_at_trx_commit != FLUSH_LOG_NEVER) { | |
| 4782 | /** | ||
| 4783 | Sync the WAL if we are in FLUSH LOGS, or if | ||
| 4784 | rocksdb_flush_log_at_trx_commit=1 | ||
| 4785 | (write and sync at each commit). | ||
| 4786 | */ | ||
| 4787 | 3367096 | rocksdb_wal_group_syncs++; | |
| 4788 |
2/4✓ Branch 0 taken 3367096 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3367096 times.
✗ Branch 3 not taken.
|
6734192 | bool sync = rdb_sync_wal_supported() && |
| 4789 |
2/2✓ Branch 0 taken 3361336 times.
✓ Branch 1 taken 5760 times.
|
3367096 | (!binlog_group_flush || |
| 4790 |
2/2✓ Branch 0 taken 3357475 times.
✓ Branch 1 taken 3861 times.
|
3361336 | rocksdb_flush_log_at_trx_commit == FLUSH_LOG_SYNC); |
| 4791 |
1/2✓ Branch 0 taken 3367096 times.
✗ Branch 1 not taken.
|
3367096 | const rocksdb::Status s = rdb->FlushWAL(sync); |
| 4792 | |||
| 4793 |
2/4✓ Branch 0 taken 3367096 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3367096 times.
|
3367096 | if (!s.ok()) { |
| 4794 | ✗ | rdb_log_status_error(s); | |
| 4795 | ✗ | DBUG_RETURN(true); | |
| 4796 | } | ||
| 4797 |
1/2✓ Branch 0 taken 3367096 times.
✗ Branch 1 not taken.
|
3367096 | } |
| 4798 | |||
| 4799 |
1/2✓ Branch 0 taken 3367096 times.
✗ Branch 1 not taken.
|
3367096 | DBUG_RETURN(false); |
| 4800 | } | ||
| 4801 | |||
| 4802 | /** | ||
| 4803 | For a slave, prepare() updates the slave_gtid_info table which tracks the | ||
| 4804 | replication progress. | ||
| 4805 | */ | ||
| 4806 | 3854871 | static int rocksdb_prepare(handlerton *const hton, THD *const thd, | |
| 4807 | bool prepare_tx) { | ||
| 4808 | 3854871 | Rdb_transaction *tx = get_tx_from_thd(thd); | |
| 4809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3854953 times.
|
3855205 | if (!tx->is_tx_started()) { |
| 4810 | // nothing to prepare | ||
| 4811 | ✗ | return HA_EXIT_SUCCESS; | |
| 4812 | } | ||
| 4813 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 3854716 times.
|
3854953 | if (!tx->can_prepare()) { |
| 4814 | 27 | return HA_EXIT_FAILURE; | |
| 4815 | } | ||
| 4816 |
4/4✓ Branch 0 taken 3825824 times.
✓ Branch 1 taken 28892 times.
✓ Branch 2 taken 3439013 times.
✓ Branch 3 taken 415641 times.
|
7680478 | if (prepare_tx || |
| 4817 |
2/2✓ Branch 0 taken 3410014 times.
✓ Branch 1 taken 415748 times.
|
3825824 | (!my_core::thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { |
| 4818 |
1/2✓ Branch 0 taken 3439053 times.
✗ Branch 1 not taken.
|
3439013 | if (thd->durability_property == HA_IGNORE_DURABILITY) { |
| 4819 | 3439053 | tx->set_sync(false); | |
| 4820 | } | ||
| 4821 | // For write unprepared, set_name is called at the start of a transaction. | ||
| 4822 |
2/2✓ Branch 0 taken 2316366 times.
✓ Branch 1 taken 1122469 times.
|
3438835 | if (rocksdb_write_policy != rocksdb::TxnDBWritePolicy::WRITE_UNPREPARED) { |
| 4823 | 2316366 | tx->set_name(); | |
| 4824 | } | ||
| 4825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3439406 times.
|
3439349 | if (!tx->prepare()) { |
| 4826 | ✗ | return HA_EXIT_FAILURE; | |
| 4827 | } | ||
| 4828 | |||
| 4829 |
1/2✓ Branch 0 taken 3439393 times.
✗ Branch 1 not taken.
|
3439406 | DEBUG_SYNC(thd, "rocksdb.prepared"); |
| 4830 | } else | ||
| 4831 | 415641 | tx->make_stmt_savepoint_permanent(); | |
| 4832 | |||
| 4833 | 3855370 | return HA_EXIT_SUCCESS; | |
| 4834 | } | ||
| 4835 | |||
| 4836 | 23 | static xa_status_code rocksdb_commit_by_xid(handlerton *const hton, | |
| 4837 | XID *const xid) { | ||
| 4838 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | DBUG_ENTER_FUNC(); |
| 4839 | |||
| 4840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(hton != nullptr); |
| 4841 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(xid != nullptr); |
| 4842 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(commit_latency_stats != nullptr); |
| 4843 | |||
| 4844 |
2/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
|
23 | auto clock = rocksdb::Env::Default()->GetSystemClock().get(); |
| 4845 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | rocksdb::StopWatchNano timer(clock, true); |
| 4846 | |||
| 4847 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | const auto name = rdb_xid_to_string(*xid); |
| 4848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(!name.empty()); |
| 4849 | |||
| 4850 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | rocksdb::Transaction *const trx = rdb->GetTransactionByName(name); |
| 4851 | |||
| 4852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | if (trx == nullptr) { |
| 4853 | ✗ | DBUG_RETURN(XAER_NOTA); | |
| 4854 | } | ||
| 4855 | |||
| 4856 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | const rocksdb::Status s = trx->Commit(); |
| 4857 | |||
| 4858 |
2/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
|
23 | if (!s.ok()) { |
| 4859 | ✗ | rdb_log_status_error(s); | |
| 4860 | ✗ | DBUG_RETURN(XAER_RMERR); | |
| 4861 | } | ||
| 4862 | |||
| 4863 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | delete trx; |
| 4864 | |||
| 4865 | // `Add()` is implemented in a thread-safe manner. | ||
| 4866 |
2/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
|
23 | commit_latency_stats->Add(timer.ElapsedNanos() / 1000); |
| 4867 | |||
| 4868 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | DBUG_RETURN(XA_OK); |
| 4869 | 23 | } | |
| 4870 | |||
| 4871 | ✗ | static xa_status_code rocksdb_rollback_by_xid( | |
| 4872 | handlerton *const hton MY_ATTRIBUTE((__unused__)), XID *const xid) { | ||
| 4873 | ✗ | DBUG_ENTER_FUNC(); | |
| 4874 | |||
| 4875 | ✗ | assert(hton != nullptr); | |
| 4876 | ✗ | assert(xid != nullptr); | |
| 4877 | ✗ | assert(rdb != nullptr); | |
| 4878 | |||
| 4879 | ✗ | const auto name = rdb_xid_to_string(*xid); | |
| 4880 | |||
| 4881 | ✗ | rocksdb::Transaction *const trx = rdb->GetTransactionByName(name); | |
| 4882 | |||
| 4883 | ✗ | if (trx == nullptr) { | |
| 4884 | ✗ | DBUG_RETURN(XAER_NOTA); | |
| 4885 | } | ||
| 4886 | |||
| 4887 | ✗ | const rocksdb::Status s = trx->Rollback(); | |
| 4888 | |||
| 4889 | ✗ | if (!s.ok()) { | |
| 4890 | ✗ | rdb_log_status_error(s); | |
| 4891 | ✗ | DBUG_RETURN(XAER_RMERR); | |
| 4892 | } | ||
| 4893 | |||
| 4894 | ✗ | delete trx; | |
| 4895 | |||
| 4896 | ✗ | DBUG_RETURN(XA_OK); | |
| 4897 | } | ||
| 4898 | |||
| 4899 | /** | ||
| 4900 | Rebuilds an XID from a serialized version stored in a string. | ||
| 4901 | */ | ||
| 4902 | 23 | static void rdb_xid_from_string(const std::string &src, XID *const dst) { | |
| 4903 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(dst != nullptr); |
| 4904 | 23 | uint offset = 0; | |
| 4905 | uint64 raw_fid8 = | ||
| 4906 | 23 | rdb_netbuf_to_uint64(reinterpret_cast<const uchar *>(src.data())); | |
| 4907 | 23 | const int64 signed_fid8 = *reinterpret_cast<int64 *>(&raw_fid8); | |
| 4908 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | dst->set_format_id(signed_fid8); |
| 4909 | 23 | offset += RDB_FORMATID_SZ; | |
| 4910 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | dst->set_gtrid_length(src.at(offset)); |
| 4911 | 23 | offset += RDB_GTRID_SZ; | |
| 4912 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | dst->set_bqual_length(src.at(offset)); |
| 4913 | 23 | offset += RDB_BQUAL_SZ; | |
| 4914 | |||
| 4915 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(dst->get_gtrid_length() >= 0); |
| 4916 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(dst->get_gtrid_length() <= MAXGTRIDSIZE); |
| 4917 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(dst->get_bqual_length() >= 0); |
| 4918 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(dst->get_bqual_length() <= MAXBQUALSIZE); |
| 4919 | |||
| 4920 | const std::string &tmp_data = src.substr( | ||
| 4921 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | RDB_XIDHDR_LEN, (dst->get_gtrid_length()) + (dst->get_bqual_length())); |
| 4922 | 23 | dst->set_data(tmp_data.data(), tmp_data.length()); | |
| 4923 | 23 | } | |
| 4924 | |||
| 4925 | 902 | static int rocksdb_recover(handlerton *hton, XA_recover_txn *txn_list, uint len, | |
| 4926 | MEM_ROOT *mem_root) { | ||
| 4927 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 902 times.
|
902 | if (len == 0 || txn_list == nullptr) { |
| 4928 | ✗ | return HA_EXIT_SUCCESS; | |
| 4929 | } | ||
| 4930 | |||
| 4931 | 902 | std::vector<rocksdb::Transaction *> trans_list; | |
| 4932 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | rdb->GetAllPreparedTransactions(&trans_list); |
| 4933 | |||
| 4934 | 902 | uint count = 0; | |
| 4935 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 902 times.
|
925 | for (auto &trans : trans_list) { |
| 4936 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | if (count >= len) { |
| 4937 | ✗ | break; | |
| 4938 | } | ||
| 4939 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | auto name = trans->GetName(); |
| 4940 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | rdb_xid_from_string(name, &(txn_list[count].id)); |
| 4941 | |||
| 4942 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
46 | txn_list[count].mod_tables = new (mem_root) List<st_handler_tablename>(); |
| 4943 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | if (!txn_list[count].mod_tables) break; |
| 4944 | |||
| 4945 | 23 | count++; | |
| 4946 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | } |
| 4947 | 902 | return count; | |
| 4948 | 902 | } | |
| 4949 | |||
| 4950 | 4004239 | static int rocksdb_commit(handlerton *const hton, THD *const thd, | |
| 4951 | bool commit_tx) { | ||
| 4952 |
1/2✓ Branch 0 taken 4004239 times.
✗ Branch 1 not taken.
|
4004239 | DBUG_ENTER_FUNC(); |
| 4953 | |||
| 4954 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4004239 times.
|
4004239 | assert(hton != nullptr); |
| 4955 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4004239 times.
|
4004239 | assert(thd != nullptr); |
| 4956 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4004239 times.
|
4004239 | assert(commit_latency_stats != nullptr); |
| 4957 | |||
| 4958 |
2/4✓ Branch 0 taken 4004239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4004239 times.
✗ Branch 3 not taken.
|
4004239 | auto clock = rocksdb::Env::Default()->GetSystemClock().get(); |
| 4959 |
1/2✓ Branch 0 taken 4004239 times.
✗ Branch 1 not taken.
|
4004239 | rocksdb::StopWatchNano timer(clock, true); |
| 4960 | |||
| 4961 | /* note: h->external_lock(F_UNLCK) is called after this function is called) */ | ||
| 4962 |
1/2✓ Branch 0 taken 4004239 times.
✗ Branch 1 not taken.
|
4004239 | Rdb_transaction *tx = get_tx_from_thd(thd); |
| 4963 | |||
| 4964 | /* this will trigger saving of perf_context information */ | ||
| 4965 |
2/4✓ Branch 0 taken 4004239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4004239 times.
✗ Branch 3 not taken.
|
4004239 | Rdb_perf_context_guard guard(tx, rocksdb_perf_context_level(thd)); |
| 4966 | |||
| 4967 |
1/2✓ Branch 0 taken 4004239 times.
✗ Branch 1 not taken.
|
4004239 | if (tx != nullptr) { |
| 4968 |
7/8✓ Branch 0 taken 3972222 times.
✓ Branch 1 taken 32017 times.
✓ Branch 2 taken 3972222 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3551518 times.
✓ Branch 5 taken 420704 times.
✓ Branch 6 taken 3583535 times.
✓ Branch 7 taken 420704 times.
|
4004239 | if (commit_tx || (!my_core::thd_test_options( |
| 4969 | thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { | ||
| 4970 | /* | ||
| 4971 | We get here | ||
| 4972 | - For a COMMIT statement that finishes a multi-statement transaction | ||
| 4973 | - For a statement that has its own transaction | ||
| 4974 | */ | ||
| 4975 |
3/4✓ Branch 0 taken 3583535 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3583532 times.
|
3583535 | if (tx->commit()) { |
| 4976 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_ERR_ROCKSDB_COMMIT_FAILED); |
| 4977 | } | ||
| 4978 | } else { | ||
| 4979 | /* | ||
| 4980 | We get here when committing a statement within a transaction. | ||
| 4981 | */ | ||
| 4982 | 420704 | tx->set_tx_failed(false); | |
| 4983 |
1/2✓ Branch 0 taken 420704 times.
✗ Branch 1 not taken.
|
420704 | tx->make_stmt_savepoint_permanent(); |
| 4984 | } | ||
| 4985 | |||
| 4986 |
3/4✓ Branch 0 taken 4004236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 140486 times.
✓ Branch 3 taken 3863750 times.
|
4004236 | if (my_core::thd_tx_isolation(thd) <= ISO_READ_COMMITTED) { |
| 4987 | // For READ_COMMITTED, we release any existing snapshot so that we will | ||
| 4988 | // see any changes that occurred since the last statement. | ||
| 4989 |
1/2✓ Branch 0 taken 140486 times.
✗ Branch 1 not taken.
|
140486 | tx->release_snapshot(); |
| 4990 | } | ||
| 4991 | } | ||
| 4992 | |||
| 4993 | // `Add()` is implemented in a thread-safe manner. | ||
| 4994 |
2/4✓ Branch 0 taken 4004236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4004236 times.
✗ Branch 3 not taken.
|
4004236 | commit_latency_stats->Add(timer.ElapsedNanos() / 1000); |
| 4995 | |||
| 4996 |
1/2✓ Branch 0 taken 4004236 times.
✗ Branch 1 not taken.
|
4004236 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 4997 | 4004239 | } | |
| 4998 | |||
| 4999 | 4036 | static int rocksdb_rollback(handlerton *const hton, THD *const thd, | |
| 5000 | bool rollback_tx) { | ||
| 5001 |
1/2✓ Branch 0 taken 4036 times.
✗ Branch 1 not taken.
|
4036 | Rdb_transaction *tx = get_tx_from_thd(thd); |
| 5002 |
2/4✓ Branch 0 taken 4036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4036 times.
✗ Branch 3 not taken.
|
4036 | Rdb_perf_context_guard guard(tx, rocksdb_perf_context_level(thd)); |
| 5003 | |||
| 5004 |
1/2✓ Branch 0 taken 4036 times.
✗ Branch 1 not taken.
|
4036 | if (tx != nullptr) { |
| 5005 |
2/2✓ Branch 0 taken 578 times.
✓ Branch 1 taken 3458 times.
|
4036 | if (rollback_tx) { |
| 5006 | /* | ||
| 5007 | We get here, when | ||
| 5008 | - ROLLBACK statement is issued. | ||
| 5009 | |||
| 5010 | Discard the changes made by the transaction | ||
| 5011 | */ | ||
| 5012 |
1/2✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
|
578 | tx->rollback(); |
| 5013 | } else { | ||
| 5014 | /* | ||
| 5015 | We get here when | ||
| 5016 | - a statement with AUTOCOMMIT=1 is being rolled back (because of some | ||
| 5017 | error) | ||
| 5018 | - a statement inside a transaction is rolled back | ||
| 5019 | */ | ||
| 5020 | |||
| 5021 |
1/2✓ Branch 0 taken 3458 times.
✗ Branch 1 not taken.
|
3458 | tx->rollback_stmt(); |
| 5022 | 3458 | tx->set_tx_failed(true); | |
| 5023 | } | ||
| 5024 | |||
| 5025 |
3/4✓ Branch 0 taken 4036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 672 times.
✓ Branch 3 taken 3364 times.
|
4036 | if (my_core::thd_tx_isolation(thd) <= ISO_READ_COMMITTED) { |
| 5026 | // For READ_COMMITTED, we release any existing snapshot so that we will | ||
| 5027 | // see any changes that occurred since the last statement. | ||
| 5028 |
1/2✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
|
672 | tx->release_snapshot(); |
| 5029 | } | ||
| 5030 | } | ||
| 5031 | 4036 | return HA_EXIT_SUCCESS; | |
| 5032 | 4036 | } | |
| 5033 | |||
| 5034 | 27 | static bool print_stats(THD *const thd, std::string const &type, | |
| 5035 | std::string const &name, std::string const &status, | ||
| 5036 | stat_print_fn *stat_print) { | ||
| 5037 | 27 | return stat_print(thd, type.c_str(), type.size(), name.c_str(), name.size(), | |
| 5038 | 27 | status.c_str(), status.size()); | |
| 5039 | } | ||
| 5040 | |||
| 5041 | 48 | static std::string format_string(const char *const format, ...) { | |
| 5042 | 48 | std::string res; | |
| 5043 | va_list args; | ||
| 5044 | va_list args_copy; | ||
| 5045 | char static_buff[256]; | ||
| 5046 | |||
| 5047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | assert(format != nullptr); |
| 5048 | |||
| 5049 | 48 | va_start(args, format); | |
| 5050 | 48 | va_copy(args_copy, args); | |
| 5051 | |||
| 5052 | // Calculate how much space we will need | ||
| 5053 | 48 | int len = vsnprintf(nullptr, 0, format, args); | |
| 5054 | 48 | va_end(args); | |
| 5055 | |||
| 5056 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (len < 0) { |
| 5057 | ✗ | res = std::string("<format error>"); | |
| 5058 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | } else if (len == 0) { |
| 5059 | // Shortcut for an empty string | ||
| 5060 | ✗ | res = std::string(""); | |
| 5061 | } else { | ||
| 5062 | // For short enough output use a static buffer | ||
| 5063 | 48 | char *buff = static_buff; | |
| 5064 | 48 | std::unique_ptr<char[]> dynamic_buff = nullptr; | |
| 5065 | |||
| 5066 | 48 | len++; // Add one for null terminator | |
| 5067 | |||
| 5068 | // for longer output use an allocated buffer | ||
| 5069 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (static_cast<uint>(len) > sizeof(static_buff)) { |
| 5070 | ✗ | dynamic_buff.reset(new char[len]); | |
| 5071 | ✗ | buff = dynamic_buff.get(); | |
| 5072 | } | ||
| 5073 | |||
| 5074 | // Now re-do the vsnprintf with the buffer which is now large enough | ||
| 5075 | 48 | (void)vsnprintf(buff, len, format, args_copy); | |
| 5076 | |||
| 5077 | // Convert to a std::string. Note we could have created a std::string | ||
| 5078 | // large enough and then converted the buffer to a 'char*' and created | ||
| 5079 | // the output in place. This would probably work but feels like a hack. | ||
| 5080 | // Since this isn't code that needs to be super-performant we are going | ||
| 5081 | // with this 'safer' method. | ||
| 5082 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | res = std::string(buff); |
| 5083 | 48 | } | |
| 5084 | |||
| 5085 | 48 | va_end(args_copy); | |
| 5086 | |||
| 5087 | 96 | return res; | |
| 5088 | } | ||
| 5089 | |||
| 5090 | class Rdb_snapshot_status : public Rdb_tx_list_walker { | ||
| 5091 | private: | ||
| 5092 | std::string m_data; | ||
| 5093 | |||
| 5094 | 39 | static std::string current_timestamp(void) { | |
| 5095 | static const char *const format = "%d-%02d-%02d %02d:%02d:%02d"; | ||
| 5096 | time_t currtime; | ||
| 5097 | struct tm currtm; | ||
| 5098 | |||
| 5099 | 39 | time(&currtime); | |
| 5100 | |||
| 5101 | 39 | localtime_r(&currtime, &currtm); | |
| 5102 | |||
| 5103 | 39 | return format_string(format, currtm.tm_year + 1900, currtm.tm_mon + 1, | |
| 5104 | currtm.tm_mday, currtm.tm_hour, currtm.tm_min, | ||
| 5105 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
78 | currtm.tm_sec); |
| 5106 | } | ||
| 5107 | |||
| 5108 | 39 | static std::string get_header(void) { | |
| 5109 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
78 | return "\n============================================================\n" + |
| 5110 | 78 | current_timestamp() + | |
| 5111 | " ROCKSDB TRANSACTION MONITOR OUTPUT\n" | ||
| 5112 | "============================================================\n" | ||
| 5113 | "---------\n" | ||
| 5114 | "SNAPSHOTS\n" | ||
| 5115 | "---------\n" | ||
| 5116 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
78 | "LIST OF SNAPSHOTS FOR EACH SESSION:\n"; |
| 5117 | } | ||
| 5118 | |||
| 5119 | static std::string get_footer(void) { | ||
| 5120 | return "-----------------------------------------\n" | ||
| 5121 | "END OF ROCKSDB TRANSACTION MONITOR OUTPUT\n" | ||
| 5122 | "=========================================\n"; | ||
| 5123 | } | ||
| 5124 | |||
| 5125 | 72 | static Rdb_deadlock_info::Rdb_dl_trx_info get_dl_txn_info( | |
| 5126 | const rocksdb::DeadlockInfo &txn, const GL_INDEX_ID &gl_index_id) { | ||
| 5127 | 72 | Rdb_deadlock_info::Rdb_dl_trx_info txn_data; | |
| 5128 | |||
| 5129 | 72 | txn_data.trx_id = txn.m_txn_id; | |
| 5130 | |||
| 5131 |
2/4✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
|
72 | txn_data.table_name = ddl_manager.safe_get_table_name(gl_index_id); |
| 5132 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 48 times.
|
72 | if (txn_data.table_name.empty()) { |
| 5133 | txn_data.table_name = | ||
| 5134 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
24 | "NOT FOUND; INDEX_ID: " + std::to_string(gl_index_id.index_id); |
| 5135 | } | ||
| 5136 | |||
| 5137 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | const auto &kd = ddl_manager.safe_find(gl_index_id); |
| 5138 | txn_data.index_name = | ||
| 5139 |
4/6✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
168 | (kd) ? kd->get_name() |
| 5140 |
4/8✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
240 | : "NOT FOUND; INDEX_ID: " + std::to_string(gl_index_id.index_id); |
| 5141 | |||
| 5142 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 5143 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | cf_manager.get_cf(txn.m_cf_id); |
| 5144 | |||
| 5145 | // Retrieve CF name from CF handle object, and it is safe if the CF is | ||
| 5146 | // removed from cf_manager at this point. | ||
| 5147 | txn_data.cf_name = (cfh) | ||
| 5148 |
5/8✓ Branch 0 taken 66 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
150 | ? cfh->GetName() |
| 5149 |
4/8✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 66 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
222 | : "NOT FOUND; CF_ID: " + std::to_string(txn.m_cf_id); |
| 5150 | |||
| 5151 | txn_data.waiting_key = | ||
| 5152 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | rdb_hexdump(txn.m_waiting_key.c_str(), txn.m_waiting_key.length()); |
| 5153 | |||
| 5154 | 72 | txn_data.exclusive_lock = txn.m_exclusive; | |
| 5155 | |||
| 5156 | 144 | return txn_data; | |
| 5157 | 72 | } | |
| 5158 | |||
| 5159 | 36 | static Rdb_deadlock_info get_dl_path_trx_info( | |
| 5160 | const rocksdb::DeadlockPath &path_entry) { | ||
| 5161 | 36 | Rdb_deadlock_info deadlock_info; | |
| 5162 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | deadlock_info.path.reserve(path_entry.path.size()); |
| 5163 | |||
| 5164 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 36 times.
|
108 | for (const auto &txn : path_entry.path) { |
| 5165 | const GL_INDEX_ID gl_index_id = { | ||
| 5166 | 72 | txn.m_cf_id, rdb_netbuf_to_uint32(reinterpret_cast<const uchar *>( | |
| 5167 | 72 | txn.m_waiting_key.c_str()))}; | |
| 5168 |
2/4✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
|
72 | deadlock_info.path.push_back(get_dl_txn_info(txn, gl_index_id)); |
| 5169 | } | ||
| 5170 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | assert_IFF(path_entry.limit_exceeded, path_entry.path.empty()); |
| 5171 | /* print the first txn in the path to display the full deadlock cycle */ | ||
| 5172 |
3/6✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 | if (!path_entry.path.empty() && !path_entry.limit_exceeded) { |
| 5173 | 36 | const auto &deadlocking_txn = *(path_entry.path.end() - 1); | |
| 5174 | 36 | deadlock_info.victim_trx_id = deadlocking_txn.m_txn_id; | |
| 5175 | 36 | deadlock_info.deadlock_time = path_entry.deadlock_time; | |
| 5176 | } | ||
| 5177 | 36 | return deadlock_info; | |
| 5178 | } | ||
| 5179 | |||
| 5180 | public: | ||
| 5181 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | Rdb_snapshot_status() : m_data(get_header()) {} |
| 5182 | |||
| 5183 | std::string getResult() { return m_data + get_footer(); } | ||
| 5184 | |||
| 5185 | /* Implement Rdb_transaction interface */ | ||
| 5186 | /* Create one row in the snapshot status table */ | ||
| 5187 | 93 | void process_tran(const Rdb_transaction *const tx) override { | |
| 5188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
|
93 | assert(tx != nullptr); |
| 5189 | |||
| 5190 | /* Calculate the duration the snapshot has existed */ | ||
| 5191 | 93 | int64_t snapshot_timestamp = tx->m_snapshot_timestamp; | |
| 5192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 93 times.
|
93 | if (snapshot_timestamp != 0) { |
| 5193 | int64_t curr_time; | ||
| 5194 | ✗ | rdb->GetEnv()->GetCurrentTime(&curr_time); | |
| 5195 | |||
| 5196 | ✗ | THD *thd = tx->get_thd(); | |
| 5197 | char buffer[1024]; | ||
| 5198 | ✗ | thd_security_context(thd, buffer, sizeof buffer, 0); | |
| 5199 | ✗ | m_data += format_string( | |
| 5200 | "---SNAPSHOT, ACTIVE %lld sec\n" | ||
| 5201 | "%s\n" | ||
| 5202 | "lock count %llu, write count %llu\n", | ||
| 5203 | curr_time - snapshot_timestamp, buffer, tx->get_row_lock_count(), | ||
| 5204 | ✗ | tx->get_write_count()); | |
| 5205 | } | ||
| 5206 | 93 | } | |
| 5207 | |||
| 5208 | 39 | std::vector<Rdb_deadlock_info> get_deadlock_info() { | |
| 5209 | 39 | std::vector<Rdb_deadlock_info> deadlock_info; | |
| 5210 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | const auto &dlock_buffer = rdb->GetDeadlockInfoBuffer(); |
| 5211 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 39 times.
|
84 | for (const auto &path_entry : dlock_buffer) { |
| 5212 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 9 times.
|
45 | if (!path_entry.limit_exceeded) { |
| 5213 |
2/4✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
|
36 | deadlock_info.push_back(get_dl_path_trx_info(path_entry)); |
| 5214 | } | ||
| 5215 | } | ||
| 5216 | 78 | return deadlock_info; | |
| 5217 | 39 | } | |
| 5218 | }; | ||
| 5219 | |||
| 5220 | /** | ||
| 5221 | * @brief | ||
| 5222 | * walks through all non-replication transactions and copies | ||
| 5223 | * out relevant information for information_schema.rocksdb_trx | ||
| 5224 | */ | ||
| 5225 | class Rdb_trx_info_aggregator : public Rdb_tx_list_walker { | ||
| 5226 | private: | ||
| 5227 | std::vector<Rdb_trx_info> *m_trx_info; | ||
| 5228 | |||
| 5229 | public: | ||
| 5230 | 77 | explicit Rdb_trx_info_aggregator(std::vector<Rdb_trx_info> *const trx_info) | |
| 5231 | 77 | : m_trx_info(trx_info) {} | |
| 5232 | |||
| 5233 | 246 | void process_tran(const Rdb_transaction *const tx) override { | |
| 5234 | static const std::map<int, std::string> state_map = { | ||
| 5235 | ✗ | {rocksdb::Transaction::STARTED, "STARTED"}, | |
| 5236 | ✗ | {rocksdb::Transaction::AWAITING_PREPARE, "AWAITING_PREPARE"}, | |
| 5237 | ✗ | {rocksdb::Transaction::PREPARED, "PREPARED"}, | |
| 5238 | ✗ | {rocksdb::Transaction::AWAITING_COMMIT, "AWAITING_COMMIT"}, | |
| 5239 | ✗ | {rocksdb::Transaction::COMMITED, "COMMITED"}, | |
| 5240 | ✗ | {rocksdb::Transaction::AWAITING_ROLLBACK, "AWAITING_ROLLBACK"}, | |
| 5241 | ✗ | {rocksdb::Transaction::ROLLEDBACK, "ROLLEDBACK"}, | |
| 5242 |
13/26✓ Branch 0 taken 24 times.
✓ Branch 1 taken 222 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 24 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 24 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 24 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 168 times.
✓ Branch 21 taken 24 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
414 | }; |
| 5243 | static const size_t trx_query_max_len = 1024; // length stolen from InnoDB | ||
| 5244 | |||
| 5245 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
|
246 | assert(tx != nullptr); |
| 5246 | |||
| 5247 | 246 | THD *const thd = tx->get_thd(); | |
| 5248 | 246 | const my_thread_id thread_id = thd->thread_id(); | |
| 5249 | |||
| 5250 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 240 times.
|
246 | if (tx->is_writebatch_trx()) { |
| 5251 | 6 | const auto wb_impl = static_cast<const Rdb_writebatch_impl *>(tx); | |
| 5252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(wb_impl); |
| 5253 |
5/10✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
|
18 | m_trx_info->push_back( |
| 5254 | {"", /* name */ | ||
| 5255 | 0, /* trx_id */ | ||
| 5256 | 6 | wb_impl->get_write_count(), 0, /* lock_count */ | |
| 5257 | 0, /* timeout_sec */ | ||
| 5258 | "", /* state */ | ||
| 5259 | "", /* waiting_key */ | ||
| 5260 | 0, /* waiting_cf_id */ | ||
| 5261 | 1, /*is_replication */ | ||
| 5262 | 1, /* skip_trx_api */ | ||
| 5263 | 6 | wb_impl->is_tx_read_only(), 0, /* deadlock detection */ | |
| 5264 | 6 | wb_impl->num_ongoing_bulk_load(), thread_id, "" /* query string */}); | |
| 5265 | } else { | ||
| 5266 | 240 | const auto tx_impl = static_cast<const Rdb_transaction_impl *>(tx); | |
| 5267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
|
240 | assert(tx_impl); |
| 5268 | 240 | const rocksdb::Transaction *rdb_trx = tx_impl->get_rdb_trx(); | |
| 5269 | |||
| 5270 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 161 times.
|
240 | if (rdb_trx == nullptr) { |
| 5271 | 79 | return; | |
| 5272 | } | ||
| 5273 | |||
| 5274 | 161 | std::string query_str; | |
| 5275 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | query_str.reserve(trx_query_max_len + 1); |
| 5276 |
2/4✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
✗ Branch 3 not taken.
|
161 | size_t query_len = thd_query_safe(thd, &query_str[0], trx_query_max_len); |
| 5277 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | query_str.resize(query_len); |
| 5278 | |||
| 5279 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | const auto state_it = state_map.find(rdb_trx->GetState()); |
| 5280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
|
161 | assert(state_it != state_map.end()); |
| 5281 | 161 | const int is_replication = (thd->rli_slave != nullptr); | |
| 5282 | uint32_t waiting_cf_id; | ||
| 5283 | 161 | std::string waiting_key; | |
| 5284 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | rdb_trx->GetWaitingTxns(&waiting_cf_id, &waiting_key), |
| 5285 | |||
| 5286 |
2/4✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
✗ Branch 3 not taken.
|
322 | m_trx_info->push_back( |
| 5287 |
2/4✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
✗ Branch 3 not taken.
|
161 | {rdb_trx->GetName(), rdb_trx->GetID(), tx_impl->get_write_count(), |
| 5288 | 161 | tx_impl->get_row_lock_count(), tx_impl->get_timeout_sec(), | |
| 5289 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | state_it->second, waiting_key, waiting_cf_id, is_replication, |
| 5290 | 0, /* skip_trx_api */ | ||
| 5291 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | tx_impl->is_tx_read_only(), rdb_trx->IsDeadlockDetect(), |
| 5292 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | tx_impl->num_ongoing_bulk_load(), thread_id, query_str}); |
| 5293 | 161 | } | |
| 5294 | } | ||
| 5295 | }; | ||
| 5296 | |||
| 5297 | /* | ||
| 5298 | returns a vector of info for all non-replication threads | ||
| 5299 | for use by information_schema.rocksdb_trx | ||
| 5300 | */ | ||
| 5301 | 77 | std::vector<Rdb_trx_info> rdb_get_all_trx_info() { | |
| 5302 | 77 | std::vector<Rdb_trx_info> trx_info; | |
| 5303 | 77 | Rdb_trx_info_aggregator trx_info_agg(&trx_info); | |
| 5304 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | Rdb_transaction::walk_tx_list(&trx_info_agg); |
| 5305 | 154 | return trx_info; | |
| 5306 | 77 | } | |
| 5307 | |||
| 5308 | /* | ||
| 5309 | returns a vector of info of recent deadlocks | ||
| 5310 | for use by information_schema.rocksdb_deadlock | ||
| 5311 | */ | ||
| 5312 | 39 | std::vector<Rdb_deadlock_info> rdb_get_deadlock_info() { | |
| 5313 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | Rdb_snapshot_status showStatus; |
| 5314 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | Rdb_transaction::walk_tx_list(&showStatus); |
| 5315 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
78 | return showStatus.get_deadlock_info(); |
| 5316 | 39 | } | |
| 5317 | |||
| 5318 | /* | ||
| 5319 | This is called for SHOW ENGINE ROCKSDB STATUS | LOGS | etc. | ||
| 5320 | |||
| 5321 | For now, produce info about live files (which gives an imprecise idea about | ||
| 5322 | what column families are there). | ||
| 5323 | */ | ||
| 5324 | 9 | static bool rocksdb_show_status(handlerton *const hton, THD *const thd, | |
| 5325 | stat_print_fn *const stat_print, | ||
| 5326 | enum ha_stat_type stat_type) { | ||
| 5327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | assert(hton != nullptr); |
| 5328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | assert(thd != nullptr); |
| 5329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | assert(stat_print != nullptr); |
| 5330 | |||
| 5331 | 9 | bool res = false; | |
| 5332 | 9 | char buf[100] = {'\0'}; | |
| 5333 | |||
| 5334 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
|
9 | if (stat_type == HA_ENGINE_STATUS) { |
| 5335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(rdb != nullptr); |
| 5336 | |||
| 5337 | 3 | std::string str; | |
| 5338 | |||
| 5339 | /* Global DB Statistics */ | ||
| 5340 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (rocksdb_stats) { |
| 5341 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str = rocksdb_stats->ToString(); |
| 5342 | |||
| 5343 | // Use the same format as internal RocksDB statistics entries to make | ||
| 5344 | // sure that output will look unified. | ||
| 5345 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(commit_latency_stats != nullptr); |
| 5346 | |||
| 5347 | 15 | snprintf(buf, sizeof(buf), | |
| 5348 | "rocksdb.commit_latency statistics " | ||
| 5349 | "Percentiles :=> 50 : %.2f 95 : %.2f " | ||
| 5350 | "99 : %.2f 100 : %.2f\n", | ||
| 5351 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | commit_latency_stats->Percentile(50), |
| 5352 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | commit_latency_stats->Percentile(95), |
| 5353 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | commit_latency_stats->Percentile(99), |
| 5354 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | commit_latency_stats->Percentile(100)); |
| 5355 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5356 | |||
| 5357 | 3 | uint64_t v = 0; | |
| 5358 | |||
| 5359 | // Retrieve additional stalling related numbers from RocksDB and append | ||
| 5360 | // them to the buffer meant for displaying detailed statistics. The intent | ||
| 5361 | // here is to avoid adding another row to the query output because of | ||
| 5362 | // just two numbers. | ||
| 5363 | // | ||
| 5364 | // NB! We're replacing hyphens with underscores in output to better match | ||
| 5365 | // the existing naming convention. | ||
| 5366 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (rdb->GetIntProperty("rocksdb.is-write-stopped", &v)) { |
| 5367 | 3 | snprintf(buf, sizeof(buf), | |
| 5368 | "rocksdb.is_write_stopped COUNT : %" PRIu64 "\n", v); | ||
| 5369 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5370 | } | ||
| 5371 | |||
| 5372 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (rdb->GetIntProperty("rocksdb.actual-delayed-write-rate", &v)) { |
| 5373 | 3 | snprintf(buf, sizeof(buf), | |
| 5374 | "rocksdb.actual_delayed_write_rate " | ||
| 5375 | "COUNT : %" PRIu64 "\n", | ||
| 5376 | v); | ||
| 5377 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5378 | } | ||
| 5379 | |||
| 5380 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | res |= print_stats(thd, "STATISTICS", "rocksdb", str, stat_print); |
| 5381 | } | ||
| 5382 | |||
| 5383 | /* Per DB stats */ | ||
| 5384 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (rdb->GetProperty("rocksdb.dbstats", &str)) { |
| 5385 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | res |= print_stats(thd, "DBSTATS", "rocksdb", str, stat_print); |
| 5386 | } | ||
| 5387 | |||
| 5388 | /* Per column family stats */ | ||
| 5389 |
3/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
|
15 | for (const auto &cf_name : cf_manager.get_cf_names()) { |
| 5390 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 5391 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | cf_manager.get_cf(cf_name); |
| 5392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!cfh) { |
| 5393 | ✗ | continue; | |
| 5394 | } | ||
| 5395 | |||
| 5396 | // Retrieve information from CF handle object. | ||
| 5397 | // Even if the CF is removed from CF_manager, the handle object | ||
| 5398 | // is valid. | ||
| 5399 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | if (!rdb->GetProperty(cfh.get(), "rocksdb.cfstats", &str)) { |
| 5400 | ✗ | continue; | |
| 5401 | } | ||
| 5402 | |||
| 5403 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | res |= print_stats(thd, "CF_COMPACTION", cf_name, str, stat_print); |
| 5404 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
15 | } |
| 5405 | |||
| 5406 | /* Memory Statistics */ | ||
| 5407 | 3 | std::vector<rocksdb::DB *> dbs; | |
| 5408 | 3 | std::unordered_set<const rocksdb::Cache *> cache_set; | |
| 5409 | 3 | size_t internal_cache_count = 0; | |
| 5410 | 3 | size_t kDefaultInternalCacheSize = 8 * 1024 * 1024; | |
| 5411 | |||
| 5412 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | dbs.push_back(rdb); |
| 5413 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | cache_set.insert(rocksdb_tbl_options->block_cache.get()); |
| 5414 | |||
| 5415 |
3/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
|
15 | for (const auto &cf_handle : cf_manager.get_all_cf()) { |
| 5416 | // It is safe if the CF handle is removed from cf_manager | ||
| 5417 | // at this point. | ||
| 5418 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | rocksdb::ColumnFamilyDescriptor cf_desc; |
| 5419 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | cf_handle->GetDescriptor(&cf_desc); |
| 5420 | 12 | auto *const table_factory = cf_desc.options.table_factory.get(); | |
| 5421 | |||
| 5422 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (table_factory != nullptr) { |
| 5423 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | std::string tf_name = table_factory->Name(); |
| 5424 | |||
| 5425 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (tf_name.find("BlockBasedTable") != std::string::npos) { |
| 5426 | const auto bbt_opt = | ||
| 5427 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | table_factory->GetOptions<rocksdb::BlockBasedTableOptions>(); |
| 5428 | |||
| 5429 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (bbt_opt != nullptr) { |
| 5430 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (bbt_opt->block_cache.get() != nullptr) { |
| 5431 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | cache_set.insert(bbt_opt->block_cache.get()); |
| 5432 | } else { | ||
| 5433 | ✗ | internal_cache_count++; | |
| 5434 | } | ||
| 5435 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | cache_set.insert(bbt_opt->block_cache_compressed.get()); |
| 5436 | } | ||
| 5437 | } | ||
| 5438 | 12 | } | |
| 5439 | 15 | } | |
| 5440 | |||
| 5441 | 3 | std::map<rocksdb::MemoryUtil::UsageType, uint64_t> temp_usage_by_type; | |
| 5442 | 3 | str.clear(); | |
| 5443 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | rocksdb::MemoryUtil::GetApproximateMemoryUsageByType(dbs, cache_set, |
| 5444 | &temp_usage_by_type); | ||
| 5445 | |||
| 5446 | 3 | snprintf(buf, sizeof(buf), "\nMemTable Total: %" PRIu64, | |
| 5447 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | temp_usage_by_type[rocksdb::MemoryUtil::kMemTableTotal]); |
| 5448 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5449 | 3 | snprintf(buf, sizeof(buf), "\nMemTable Unflushed: %" PRIu64, | |
| 5450 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | temp_usage_by_type[rocksdb::MemoryUtil::kMemTableUnFlushed]); |
| 5451 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5452 | 3 | snprintf(buf, sizeof(buf), "\nTable Readers Total: %" PRIu64, | |
| 5453 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | temp_usage_by_type[rocksdb::MemoryUtil::kTableReadersTotal]); |
| 5454 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5455 | 3 | snprintf(buf, sizeof(buf), "\nCache Total: %" PRIu64, | |
| 5456 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | temp_usage_by_type[rocksdb::MemoryUtil::kCacheTotal]); |
| 5457 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5458 | 3 | snprintf(buf, sizeof(buf), "\nDefault Cache Capacity: %" PRIu64, | |
| 5459 | internal_cache_count * | ||
| 5460 | static_cast<uint64_t>(kDefaultInternalCacheSize)); | ||
| 5461 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | str.append(buf); |
| 5462 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | res |= print_stats(thd, "MEMORY_STATS", "rocksdb", str, stat_print); |
| 5463 | |||
| 5464 | /* Show the background thread status */ | ||
| 5465 | 3 | std::vector<rocksdb::ThreadStatus> thread_list; | |
| 5466 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | rocksdb::Status s = rdb->GetEnv()->GetThreadList(&thread_list); |
| 5467 | |||
| 5468 | // GetThreadList() may return Status::NotSupported when | ||
| 5469 | // ROCKSDB_USING_THREAD_STATUS is not defined | ||
| 5470 |
3/10✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
3 | if (!s.ok() && !s.IsNotSupported()) { |
| 5471 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 5472 | "Returned error (%s) from GetThreadList.\n", | ||
| 5473 | s.ToString().c_str()); | ||
| 5474 | ✗ | res |= true; | |
| 5475 | } else { | ||
| 5476 | /* For each background thread retrieved, print out its information */ | ||
| 5477 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | for (auto &it : thread_list) { |
| 5478 | /* Only look at background threads. Ignore user threads, if any. */ | ||
| 5479 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (it.thread_type > rocksdb::ThreadStatus::LOW_PRIORITY) { |
| 5480 | ✗ | continue; | |
| 5481 | } | ||
| 5482 | |||
| 5483 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | str = "\nthread_type: " + it.GetThreadTypeName(it.thread_type) + |
| 5484 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | "\ncf_name: " + it.cf_name + |
| 5485 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
18 | "\noperation_type: " + it.GetOperationName(it.operation_type) + |
| 5486 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
12 | "\noperation_stage: " + |
| 5487 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
18 | it.GetOperationStageName(it.operation_stage) + |
| 5488 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
18 | "\nelapsed_time_ms: " + it.MicrosToString(it.op_elapsed_micros); |
| 5489 | |||
| 5490 | 6 | for (auto &it_props : it.InterpretOperationProperties( | |
| 5491 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
12 | it.operation_type, it.op_properties)) { |
| 5492 | ✗ | str += "\n" + it_props.first + ": " + std::to_string(it_props.second); | |
| 5493 | 6 | } | |
| 5494 | |||
| 5495 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | str += "\nstate_type: " + it.GetStateName(it.state_type); |
| 5496 | |||
| 5497 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | res |= print_stats(thd, "BG_THREADS", std::to_string(it.thread_id), str, |
| 5498 | stat_print); | ||
| 5499 | } | ||
| 5500 | } | ||
| 5501 | 3 | } | |
| 5502 | |||
| 5503 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (res) { |
| 5504 | ✗ | my_error(ER_UNKNOWN_ERROR, MYF(0), "SHOW ENGINE"); | |
| 5505 | } | ||
| 5506 | 9 | return res; | |
| 5507 | } | ||
| 5508 | |||
| 5509 | /* | ||
| 5510 | Implements Log_resource lock. | ||
| 5511 | |||
| 5512 | returns false on success | ||
| 5513 | */ | ||
| 5514 | 6 | static bool rocksdb_lock_hton_log(handlerton *const /* unused */) { | |
| 5515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(rdb != nullptr); |
| 5516 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | return !rdb->LockWAL().ok(); |
| 5517 | } | ||
| 5518 | |||
| 5519 | /* | ||
| 5520 | Implements Log_resource unlock. | ||
| 5521 | |||
| 5522 | returns false on success | ||
| 5523 | */ | ||
| 5524 | 6 | static bool rocksdb_unlock_hton_log(handlerton *const /* unused */) { | |
| 5525 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(rdb != nullptr); |
| 5526 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | return !rdb->UnlockWAL().ok(); |
| 5527 | } | ||
| 5528 | |||
| 5529 | /* | ||
| 5530 | Implements Log_resource collect_info. | ||
| 5531 | |||
| 5532 | Produces JSON object with following structure: | ||
| 5533 | |||
| 5534 | "RocksDB": { | ||
| 5535 | "wal_files": [ | ||
| 5536 | { "log_number": N, "path_name": "...", "file_size_bytes": K }, | ||
| 5537 | ... | ||
| 5538 | ] | ||
| 5539 | } | ||
| 5540 | |||
| 5541 | returns JSON dom to receive the log info | ||
| 5542 | */ | ||
| 5543 | 6 | static bool rocksdb_collect_hton_log_info(handlerton *const /* unused */, | |
| 5544 | Json_dom *json) { | ||
| 5545 | 6 | bool ret_val = false; | |
| 5546 | 6 | rocksdb::VectorLogPtr live_wal_files; | |
| 5547 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | const auto s = rdb->GetSortedWalFiles(live_wal_files); |
| 5548 | |||
| 5549 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (!s.ok()) { |
| 5550 | ✗ | return true; | |
| 5551 | } | ||
| 5552 | |||
| 5553 | 6 | Json_object *json_engines = static_cast<Json_object *>(json); | |
| 5554 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | Json_object json_rocksdb; |
| 5555 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | Json_array json_wal_files; |
| 5556 | |||
| 5557 | 6 | size_t index = 0; | |
| 5558 |
2/2✓ Branch 0 taken 118 times.
✓ Branch 1 taken 6 times.
|
124 | for (const auto &wal : live_wal_files) { |
| 5559 |
1/2✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
|
118 | Json_uint json_log_number(wal->LogNumber()); |
| 5560 |
1/2✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
|
118 | Json_string json_path_name(wal->PathName()); |
| 5561 |
1/2✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
|
118 | Json_uint json_size_file_bytes(wal->SizeFileBytes()); |
| 5562 | |||
| 5563 |
1/2✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
|
118 | Json_object json_wal; |
| 5564 |
2/4✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
|
118 | ret_val = json_wal.add_clone("log_number", &json_log_number); |
| 5565 |
3/6✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
|
118 | if (!ret_val) json_wal.add_clone("path_name", &json_path_name); |
| 5566 |
3/6✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
|
118 | if (!ret_val) json_wal.add_clone("size_file_bytes", &json_size_file_bytes); |
| 5567 |
2/4✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
|
118 | if (!ret_val) json_wal_files.insert_clone(index, &json_wal); |
| 5568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
|
118 | if (ret_val) break; |
| 5569 | 118 | ++index; | |
| 5570 |
4/8✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 118 times.
✗ Branch 7 not taken.
|
118 | } |
| 5571 | |||
| 5572 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | if (!ret_val) ret_val = json_rocksdb.add_clone("wal_files", &json_wal_files); |
| 5573 | |||
| 5574 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | if (!ret_val) ret_val = json_engines->add_clone("RocksDB", &json_rocksdb); |
| 5575 | |||
| 5576 | 6 | return ret_val; | |
| 5577 | 6 | } | |
| 5578 | |||
| 5579 | 3983747 | static inline void rocksdb_register_tx(handlerton *const hton, THD *const thd, | |
| 5580 | Rdb_transaction *const tx) { | ||
| 5581 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3983747 times.
|
3983747 | assert(tx != nullptr); |
| 5582 | |||
| 5583 | 3983747 | trans_register_ha(thd, false, rocksdb_hton, nullptr); | |
| 5584 |
2/2✓ Branch 0 taken 1303204 times.
✓ Branch 1 taken 2680945 times.
|
3984149 | if (rocksdb_write_policy == rocksdb::TxnDBWritePolicy::WRITE_UNPREPARED) { |
| 5585 | // Some internal operations will call trans_register_ha, but they do not | ||
| 5586 | // go through 2pc. In this case, the xid is set with query_id == 0, which | ||
| 5587 | // means that rocksdb will receive transactions with duplicate names. | ||
| 5588 | // | ||
| 5589 | // Skip setting name in these cases. | ||
| 5590 |
1/2✓ Branch 0 taken 1303215 times.
✗ Branch 1 not taken.
|
1303204 | if (thd->query_id != 0) { |
| 5591 | 1303215 | tx->set_name(); | |
| 5592 | } | ||
| 5593 | } | ||
| 5594 |
2/2✓ Branch 0 taken 423926 times.
✓ Branch 1 taken 3560247 times.
|
3984185 | if (my_core::thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 5595 | 423926 | tx->start_stmt(); | |
| 5596 | 423926 | trans_register_ha(thd, true, rocksdb_hton, nullptr); | |
| 5597 | } | ||
| 5598 | 3984173 | } | |
| 5599 | |||
| 5600 | /* | ||
| 5601 | Supporting START TRANSACTION WITH CONSISTENT SNAPSHOT | ||
| 5602 | |||
| 5603 | - START TRANSACTION WITH CONSISTENT SNAPSHOT | ||
| 5604 | takes both InnoDB and RocksDB snapshots, and both InnoDB and RocksDB | ||
| 5605 | participate in transaction. When executing COMMIT, both InnoDB and | ||
| 5606 | RocksDB modifications are committed. Remember that XA is not supported yet, | ||
| 5607 | so mixing engines is not recommended anyway. | ||
| 5608 | */ | ||
| 5609 | 56 | static int rocksdb_start_tx_and_assign_read_view( | |
| 5610 | handlerton *const hton, /*!< in: RocksDB handlerton */ | ||
| 5611 | THD *const thd) /*!< in: MySQL thread handle of the | ||
| 5612 | user for whom the transaction should | ||
| 5613 | be committed */ | ||
| 5614 | { | ||
| 5615 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | ulong const tx_isolation = my_core::thd_tx_isolation(thd); |
| 5616 | |||
| 5617 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | Rdb_transaction *tx = get_or_create_tx(thd); |
| 5618 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | Rdb_perf_context_guard guard(tx, rocksdb_perf_context_level(thd)); |
| 5619 | |||
| 5620 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | assert(!tx->has_snapshot()); |
| 5621 | 56 | tx->set_tx_read_only(true); | |
| 5622 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | rocksdb_register_tx(hton, thd, tx); |
| 5623 | |||
| 5624 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (tx_isolation == ISO_REPEATABLE_READ) { |
| 5625 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | tx->acquire_snapshot(true); |
| 5626 | } else { | ||
| 5627 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 5628 | "RocksDB: Only REPEATABLE READ isolation level is " | ||
| 5629 | "supported for START TRANSACTION WITH CONSISTENT " | ||
| 5630 | "SNAPSHOT in RocksDB Storage Engine. Snapshot has not " | ||
| 5631 | "been taken."); | ||
| 5632 | } | ||
| 5633 | 56 | return HA_EXIT_SUCCESS; | |
| 5634 | 56 | } | |
| 5635 | |||
| 5636 | /* Dummy SAVEPOINT support. This is needed for long running transactions | ||
| 5637 | * like mysqldump (https://bugs.mysql.com/bug.php?id=71017). | ||
| 5638 | * Current SAVEPOINT does not correctly handle ROLLBACK and does not return | ||
| 5639 | * errors. This needs to be addressed in future versions (Issue#96). | ||
| 5640 | */ | ||
| 5641 | 60 | static int rocksdb_savepoint(handlerton *const hton, THD *const thd, | |
| 5642 | void *const savepoint) { | ||
| 5643 | 60 | return HA_EXIT_SUCCESS; | |
| 5644 | } | ||
| 5645 | |||
| 5646 | 45 | static int rocksdb_rollback_to_savepoint(handlerton *const hton, THD *const thd, | |
| 5647 | void *const savepoint) { | ||
| 5648 | 45 | Rdb_transaction *tx = get_tx_from_thd(thd); | |
| 5649 | 45 | return tx->rollback_to_savepoint(savepoint); | |
| 5650 | } | ||
| 5651 | |||
| 5652 | 18 | static bool rocksdb_rollback_to_savepoint_can_release_mdl( | |
| 5653 | handlerton *const hton, THD *const thd) { | ||
| 5654 | 18 | return true; | |
| 5655 | } | ||
| 5656 | |||
| 5657 | 463288 | static void rocksdb_get_stats(ha_statistics *stats, Rdb_tbl_def *tbl_def) { | |
| 5658 | 463288 | stats->records = 0; | |
| 5659 | 463288 | stats->index_file_length = 0ul; | |
| 5660 | 463288 | stats->data_file_length = 0ul; | |
| 5661 | 463288 | stats->mean_rec_length = 0; | |
| 5662 | |||
| 5663 |
2/2✓ Branch 0 taken 757322 times.
✓ Branch 1 taken 463289 times.
|
1220611 | for (uint i = 0; i < tbl_def->m_key_count; i++) { |
| 5664 | 757322 | auto key_def = tbl_def->m_key_descr_arr[i]; | |
| 5665 |
2/2✓ Branch 0 taken 463288 times.
✓ Branch 1 taken 294034 times.
|
757324 | if (key_def->is_primary_key()) { |
| 5666 | 463288 | stats->data_file_length = key_def->m_stats.m_actual_disk_size; | |
| 5667 | 463288 | stats->records = key_def->m_stats.m_rows; | |
| 5668 | } else { | ||
| 5669 | 294034 | stats->index_file_length += key_def->m_stats.m_actual_disk_size; | |
| 5670 | } | ||
| 5671 | 757320 | } | |
| 5672 | 463289 | } | |
| 5673 | |||
| 5674 | /* | ||
| 5675 | This is called for INFORMATION_SCHEMA.TABLES | ||
| 5676 | */ | ||
| 5677 | 402 | static bool rocksdb_get_table_statistics( | |
| 5678 | const char *db_name, const char *table_name, | ||
| 5679 | dd::Object_id /*se_private_id*/, | ||
| 5680 | const dd::Properties & /*ts_se_private_data*/, | ||
| 5681 | const dd::Properties & /*tbl_se_private_data*/, uint /*stat_flags*/, | ||
| 5682 | ha_statistics *stats) { | ||
| 5683 |
1/2✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
|
402 | std::string fullname = db_name; |
| 5684 |
1/2✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
|
402 | fullname.append("."); |
| 5685 |
1/2✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
|
402 | fullname.append(table_name); |
| 5686 | |||
| 5687 | // We are called from within metadata lock MDL_EXPLICIT, so it should be | ||
| 5688 | // safe to access Rdb_tbl_def here | ||
| 5689 |
1/2✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
|
402 | auto tbl_def = ddl_manager.find(fullname); |
| 5690 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 396 times.
|
402 | if (!tbl_def) { |
| 5691 | // Table is missing due to a possible race condition | ||
| 5692 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(HA_ERR_NO_SUCH_TABLE, MYF(0), "Table is missing"); |
| 5693 | 6 | return true; | |
| 5694 | } | ||
| 5695 | |||
| 5696 |
1/2✓ Branch 0 taken 396 times.
✗ Branch 1 not taken.
|
396 | int ret = ha_rocksdb::update_stats(stats, tbl_def); |
| 5697 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 396 times.
|
396 | if (ret != HA_EXIT_SUCCESS) { |
| 5698 | ✗ | my_error(ret, MYF(0), "Failed to update table stats"); | |
| 5699 | ✗ | return true; | |
| 5700 | } | ||
| 5701 | |||
| 5702 | 396 | return false; | |
| 5703 | 402 | } | |
| 5704 | |||
| 5705 | 920 | static rocksdb::Status check_rocksdb_options_compatibility( | |
| 5706 | const char *const dbpath, const rocksdb::Options &main_opts, | ||
| 5707 | const std::vector<rocksdb::ColumnFamilyDescriptor> &cf_descr) { | ||
| 5708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 920 times.
|
920 | assert(rocksdb_datadir != nullptr); |
| 5709 | |||
| 5710 |
1/2✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
|
920 | rocksdb::DBOptions loaded_db_opt; |
| 5711 | 920 | std::vector<rocksdb::ColumnFamilyDescriptor> loaded_cf_descs; | |
| 5712 | rocksdb::Status status = | ||
| 5713 | 920 | LoadLatestOptions(dbpath, main_opts.env, &loaded_db_opt, &loaded_cf_descs, | |
| 5714 |
2/4✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 920 times.
✗ Branch 3 not taken.
|
1840 | rocksdb_ignore_unknown_options); |
| 5715 | |||
| 5716 | // If we're starting from scratch and there are no options saved yet then this | ||
| 5717 | // is a valid case. Therefore we can't compare the current set of options to | ||
| 5718 | // anything. | ||
| 5719 |
3/4✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
✓ Branch 3 taken 517 times.
|
920 | if (status.IsNotFound()) { |
| 5720 | 403 | return rocksdb::Status::OK(); | |
| 5721 | } | ||
| 5722 | |||
| 5723 |
3/4✓ Branch 0 taken 517 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 514 times.
|
517 | if (!status.ok()) { |
| 5724 | 3 | return status; | |
| 5725 | } | ||
| 5726 | |||
| 5727 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 514 times.
|
514 | if (loaded_cf_descs.size() != cf_descr.size()) { |
| 5728 | return rocksdb::Status::NotSupported( | ||
| 5729 | "Mismatched size of column family " | ||
| 5730 | ✗ | "descriptors."); | |
| 5731 | } | ||
| 5732 | |||
| 5733 | // Please see RocksDB documentation for more context about why we need to set | ||
| 5734 | // user-defined functions and pointer-typed options manually. | ||
| 5735 |
2/2✓ Branch 0 taken 2291 times.
✓ Branch 1 taken 514 times.
|
2805 | for (size_t i = 0; i < loaded_cf_descs.size(); i++) { |
| 5736 | 4582 | loaded_cf_descs[i].options.compaction_filter = | |
| 5737 | 2291 | cf_descr[i].options.compaction_filter; | |
| 5738 | 2291 | loaded_cf_descs[i].options.compaction_filter_factory = | |
| 5739 | 2291 | cf_descr[i].options.compaction_filter_factory; | |
| 5740 | 2291 | loaded_cf_descs[i].options.comparator = cf_descr[i].options.comparator; | |
| 5741 | 2291 | loaded_cf_descs[i].options.memtable_factory = | |
| 5742 | 2291 | cf_descr[i].options.memtable_factory; | |
| 5743 | 2291 | loaded_cf_descs[i].options.merge_operator = | |
| 5744 | 2291 | cf_descr[i].options.merge_operator; | |
| 5745 | 2291 | loaded_cf_descs[i].options.prefix_extractor = | |
| 5746 | 2291 | cf_descr[i].options.prefix_extractor; | |
| 5747 | 2291 | loaded_cf_descs[i].options.table_factory = | |
| 5748 | 2291 | cf_descr[i].options.table_factory; | |
| 5749 | } | ||
| 5750 | |||
| 5751 | // This is the essence of the function - determine if it's safe to open the | ||
| 5752 | // database or not. | ||
| 5753 |
2/4✓ Branch 0 taken 514 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 514 times.
✗ Branch 3 not taken.
|
1028 | status = CheckOptionsCompatibility(dbpath, main_opts.env, main_opts, |
| 5754 | loaded_cf_descs, | ||
| 5755 | 514 | rocksdb_ignore_unknown_options); | |
| 5756 | |||
| 5757 | 514 | return status; | |
| 5758 | 920 | } | |
| 5759 | |||
| 5760 | 45358 | static uint rocksdb_partition_flags() { return (HA_CANNOT_PARTITION_FK); } | |
| 5761 | |||
| 5762 | 1058 | bool rdb_has_wsenv() { | |
| 5763 | #if FB_HAVE_WSENV | ||
| 5764 | return rocksdb_wsenv_path != nullptr && *rocksdb_wsenv_path; | ||
| 5765 | #else | ||
| 5766 | 1058 | return false; | |
| 5767 | #endif | ||
| 5768 | } | ||
| 5769 | |||
| 5770 | 7006222 | bool rdb_sync_wal_supported() { | |
| 5771 | #if FB_HAVE_WSENV | ||
| 5772 | // wsenv doesn't support SyncWAL=true yet | ||
| 5773 | return !rdb_has_wsenv(); | ||
| 5774 | #else | ||
| 5775 | 7006222 | return true; | |
| 5776 | #endif | ||
| 5777 | } | ||
| 5778 | |||
| 5779 | /* Clean up tables leftover from truncation */ | ||
| 5780 | 902 | void rocksdb_truncation_table_cleanup(void) { | |
| 5781 | /* Scan for tables that have the truncation prefix */ | ||
| 5782 | struct Rdb_truncate_tbls : public Rdb_tables_scanner { | ||
| 5783 | public: | ||
| 5784 | std::vector<Rdb_tbl_def *> m_tbl_list; | ||
| 5785 | 947 | int add_table(Rdb_tbl_def *tdef) override { | |
| 5786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 947 times.
|
947 | assert(tdef != nullptr); |
| 5787 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 944 times.
|
947 | if (tdef->base_tablename().find(TRUNCATE_TABLE_PREFIX) != |
| 5788 | std::string::npos) { | ||
| 5789 | 3 | m_tbl_list.push_back(tdef); | |
| 5790 | } | ||
| 5791 | 947 | return HA_EXIT_SUCCESS; | |
| 5792 | } | ||
| 5793 | 902 | } collector; | |
| 5794 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | ddl_manager.scan_for_tables(&collector); |
| 5795 | |||
| 5796 | /* | ||
| 5797 | For now, delete any table found. It's possible to rename them back, | ||
| 5798 | but there's a risk the rename can potentially lead to other inconsistencies. | ||
| 5799 | Removing the old table (which is being truncated anyway) seems to be the | ||
| 5800 | safest solution. | ||
| 5801 | */ | ||
| 5802 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | ha_rocksdb table(rocksdb_hton, nullptr); |
| 5803 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 902 times.
|
905 | for (Rdb_tbl_def *tbl_def : collector.m_tbl_list) { |
| 5804 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(WARNING_LEVEL, 0, "Removing truncated leftover table %s", |
| 5805 | tbl_def->full_tablename().c_str()); | ||
| 5806 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | table.delete_table(tbl_def); |
| 5807 | } | ||
| 5808 | 902 | } | |
| 5809 | |||
| 5810 | /* | ||
| 5811 | Storage Engine initialization function, invoked when plugin is loaded. | ||
| 5812 | */ | ||
| 5813 | |||
| 5814 | 935 | static int rocksdb_init_internal(void *const p) { | |
| 5815 |
1/2✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
|
935 | DBUG_ENTER_FUNC(); |
| 5816 | |||
| 5817 | // Validate the assumption about the size of ROCKSDB_SIZEOF_HIDDEN_PK_COLUMN. | ||
| 5818 | static_assert(sizeof(longlong) == 8, "Assuming that longlong is 8 bytes."); | ||
| 5819 | |||
| 5820 | // Lock the handlertons initialized status flag for writing | ||
| 5821 |
2/4✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 935 times.
✗ Branch 3 not taken.
|
935 | Rdb_hton_init_state::Scoped_lock state_lock(*rdb_get_hton_init_state(), true); |
| 5822 |
2/6✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 935 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
935 | SHIP_ASSERT(!rdb_get_hton_init_state()->initialized()); |
| 5823 | |||
| 5824 | // Initialize error logging service. | ||
| 5825 |
2/4✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 935 times.
|
935 | if (init_logging_service_for_plugin(®_srv, &log_bi, &log_bs)) { |
| 5826 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 5827 | } | ||
| 5828 | |||
| 5829 |
5/6✓ Branch 0 taken 935 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 931 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 932 times.
|
939 | if (THDVAR(nullptr, write_disable_wal) && |
| 5830 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | rocksdb_flush_log_at_trx_commit == FLUSH_LOG_SYNC) { |
| 5831 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 5832 | "Invalid argument: Sync writes " | ||
| 5833 | "(rocksdb_flush_log_at_trx_commit == 1) has to enable WAL"); | ||
| 5834 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(1); |
| 5835 | } | ||
| 5836 | |||
| 5837 | #ifdef FB_HAVE_WSENV | ||
| 5838 | // Initialize WSEnv with rocksdb_ws_env_path | ||
| 5839 | if (rdb_has_wsenv()) { | ||
| 5840 | LogPluginErrMsg( | ||
| 5841 | INFORMATION_LEVEL, 0, | ||
| 5842 | "RocksDB: Initializing WSEnvironment: rocksdb_wsenv_path = %s", | ||
| 5843 | rocksdb_wsenv_path); | ||
| 5844 | |||
| 5845 | RegisterCustomObjectsSimple(); | ||
| 5846 | rocksdb::Env *ws_env = nullptr; | ||
| 5847 | auto s = rocksdb::Env::LoadEnv(rocksdb_wsenv_path, &ws_env); | ||
| 5848 | if (s.ok()) { | ||
| 5849 | rocksdb_db_options->env = ws_env; | ||
| 5850 | } else { | ||
| 5851 | rdb_log_status_error(s, "Can't initialize WSEnvironment"); | ||
| 5852 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 5853 | } | ||
| 5854 | } | ||
| 5855 | #else | ||
| 5856 |
2/4✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 932 times.
|
932 | if (rocksdb_wsenv_path != nullptr && *rocksdb_wsenv_path) { |
| 5857 | // We've turned on WSEnv in the wrong build | ||
| 5858 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "WSEnvironment not supported. "); | |
| 5859 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 5860 | } | ||
| 5861 | #endif | ||
| 5862 | |||
| 5863 |
2/4✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 932 times.
|
932 | if (rdb_has_rocksdb_corruption()) { |
| 5864 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 5865 | "There was corruption detected in the RockDB data files. " | ||
| 5866 | "Check error log emitted earlier for more details."); | ||
| 5867 | ✗ | if (rocksdb_allow_to_start_after_corruption) { | |
| 5868 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 5869 | "Set rocksdb_allow_to_start_after_corruption=0 to " | ||
| 5870 | "prevent server from starting when RocksDB data " | ||
| 5871 | "corruption is detected."); | ||
| 5872 | } else { | ||
| 5873 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 5874 | "The server will exit normally and stop restart " | ||
| 5875 | "attempts. Remove %s file from data directory and start " | ||
| 5876 | "mysqld manually.", | ||
| 5877 | rdb_corruption_marker_file_name().c_str()); | ||
| 5878 | ✗ | exit(0); | |
| 5879 | } | ||
| 5880 | } | ||
| 5881 | |||
| 5882 | 932 | rocksdb::Status s; | |
| 5883 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 932 times.
|
932 | if (rocksdb_fs_uri) { |
| 5884 | ✗ | std::shared_ptr<rocksdb::FileSystem> fs; | |
| 5885 | ✗ | s = rocksdb::FileSystem::Load(rocksdb_fs_uri, &fs); | |
| 5886 | ✗ | if (fs == nullptr) { | |
| 5887 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Loading custom file system failed: %s\n", | |
| 5888 | s.ToString().c_str()); | ||
| 5889 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 5890 | } | ||
| 5891 | ✗ | rocksdb_db_options->env = GetCompositeEnv(fs); | |
| 5892 | } | ||
| 5893 | |||
| 5894 |
2/6✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 932 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
932 | DBUG_EXECUTE_IF("rocksdb_init_failure_files_corruption", |
| 5895 | { DBUG_RETURN(HA_EXIT_FAILURE); }); | ||
| 5896 | |||
| 5897 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 926 times.
|
932 | if (opt_rocksdb_fault_injection_options != nullptr && |
| 5898 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | *opt_rocksdb_fault_injection_options != '\0') { |
| 5899 | 3 | bool retryable = false; | |
| 5900 | 3 | uint32_t failure_ratio = 0; | |
| 5901 | 3 | std::vector<rocksdb::FileType> types; | |
| 5902 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (parse_fault_injection_params(&retryable, &failure_ratio, &types)) { |
| 5903 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 5904 | } | ||
| 5905 | |||
| 5906 | auto fs = std::make_shared<rocksdb::FaultInjectionTestFS>( | ||
| 5907 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | rocksdb_db_options->env->GetFileSystem()); |
| 5908 | |||
| 5909 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rocksdb::IOStatus error_msg = rocksdb::IOStatus::IOError("IO Error"); |
| 5910 | 3 | error_msg.SetRetryable(retryable); | |
| 5911 | |||
| 5912 | 3 | uint32_t seed = rand(); | |
| 5913 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 5914 | "Initializing fault injection with params (retry=%d, " | ||
| 5915 | "failure_ratio=%d, seed=%d)", | ||
| 5916 | retryable, failure_ratio, seed); | ||
| 5917 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | fs->SetRandomWriteError(seed, failure_ratio, error_msg, |
| 5918 | /* inject_for_all_file_types */ false, types); | ||
| 5919 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | fs->EnableWriteErrorInjection(); |
| 5920 | |||
| 5921 | static auto fault_env_guard = | ||
| 5922 | 6 | std::make_shared<rocksdb::CompositeEnvWrapper>(rocksdb_db_options->env, | |
| 5923 |
3/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
3 | fs); |
| 5924 | 3 | rocksdb_db_options->env = fault_env_guard.get(); | |
| 5925 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | } |
| 5926 | |||
| 5927 | // Validate the assumption about the size of ROCKSDB_SIZEOF_HIDDEN_PK_COLUMN. | ||
| 5928 | static_assert(sizeof(longlong) == 8, "Assuming that longlong is 8 bytes."); | ||
| 5929 | |||
| 5930 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | init_rocksdb_psi_keys(); |
| 5931 | |||
| 5932 | 932 | rocksdb_hton = (handlerton *)p; | |
| 5933 | |||
| 5934 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_open_tables.init(); |
| 5935 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
962 | Ensure_cleanup rdb_open_tables_cleanup([]() { rdb_open_tables.free(); }); |
| 5936 | |||
| 5937 | #ifdef HAVE_PSI_INTERFACE | ||
| 5938 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_bg_thread.init(rdb_signal_bg_psi_mutex_key, rdb_signal_bg_psi_cond_key); |
| 5939 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_drop_idx_thread.init(rdb_signal_drop_idx_psi_mutex_key, |
| 5940 | rdb_signal_drop_idx_psi_cond_key); | ||
| 5941 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_is_thread.init(rdb_signal_is_psi_mutex_key, rdb_signal_is_psi_cond_key); |
| 5942 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_mc_thread.init(rdb_signal_mc_psi_mutex_key, rdb_signal_mc_psi_cond_key); |
| 5943 | #else | ||
| 5944 | rdb_bg_thread.init(); | ||
| 5945 | rdb_drop_idx_thread.init(); | ||
| 5946 | rdb_is_thread.init(); | ||
| 5947 | rdb_mc_thread.init(); | ||
| 5948 | #endif | ||
| 5949 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_collation_data_mutex.init(rdb_collation_data_mutex_key, |
| 5950 | MY_MUTEX_INIT_FAST); | ||
| 5951 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_mem_cmp_space_mutex.init(rdb_mem_cmp_space_mutex_key, MY_MUTEX_INIT_FAST); |
| 5952 | |||
| 5953 | #if defined(HAVE_PSI_INTERFACE) | ||
| 5954 | 932 | rdb_collation_exceptions = | |
| 5955 |
2/4✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932 times.
✗ Branch 3 not taken.
|
932 | new Regex_list_handler(key_rwlock_collation_exception_list); |
| 5956 | #else | ||
| 5957 | rdb_collation_exceptions = new Regex_list_handler(); | ||
| 5958 | #endif | ||
| 5959 | |||
| 5960 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_sysvars_mutex.init(rdb_sysvars_psi_mutex_key, MY_MUTEX_INIT_FAST); |
| 5961 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_block_cache_resize_mutex.init(rdb_block_cache_resize_mutex_key, |
| 5962 | MY_MUTEX_INIT_FAST); | ||
| 5963 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rdb_bottom_pri_background_compactions_resize_mutex.init( |
| 5964 | rdb_bottom_pri_background_compactions_resize_mutex_key, | ||
| 5965 | MY_MUTEX_INIT_FAST); | ||
| 5966 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | Rdb_transaction::init_mutex(); |
| 5967 | |||
| 5968 |
2/6✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 932 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
932 | DBUG_EXECUTE_IF("rocksdb_init_failure_mutexes_initialized", { |
| 5969 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 5970 | }); | ||
| 5971 | |||
| 5972 | 932 | rocksdb_hton->state = SHOW_OPTION_YES; | |
| 5973 | 932 | rocksdb_hton->create = rocksdb_create_handler; | |
| 5974 | 932 | rocksdb_hton->close_connection = rocksdb_close_connection; | |
| 5975 | 932 | rocksdb_hton->prepare = rocksdb_prepare; | |
| 5976 | 932 | rocksdb_hton->commit_by_xid = rocksdb_commit_by_xid; | |
| 5977 | 932 | rocksdb_hton->rollback_by_xid = rocksdb_rollback_by_xid; | |
| 5978 | 932 | rocksdb_hton->recover = rocksdb_recover; | |
| 5979 | 932 | rocksdb_hton->commit = rocksdb_commit; | |
| 5980 | 932 | rocksdb_hton->rollback = rocksdb_rollback; | |
| 5981 | 932 | rocksdb_hton->db_type = DB_TYPE_ROCKSDB; | |
| 5982 | 932 | rocksdb_hton->show_status = rocksdb_show_status; | |
| 5983 | 932 | rocksdb_hton->lock_hton_log = rocksdb_lock_hton_log; | |
| 5984 | 932 | rocksdb_hton->unlock_hton_log = rocksdb_unlock_hton_log; | |
| 5985 | 932 | rocksdb_hton->collect_hton_log_info = rocksdb_collect_hton_log_info; | |
| 5986 | 932 | rocksdb_hton->start_consistent_snapshot = | |
| 5987 | rocksdb_start_tx_and_assign_read_view; | ||
| 5988 | 932 | rocksdb_hton->savepoint_set = rocksdb_savepoint; | |
| 5989 | 932 | rocksdb_hton->savepoint_rollback = rocksdb_rollback_to_savepoint; | |
| 5990 | 932 | rocksdb_hton->savepoint_rollback_can_release_mdl = | |
| 5991 | rocksdb_rollback_to_savepoint_can_release_mdl; | ||
| 5992 | 932 | rocksdb_hton->get_table_statistics = rocksdb_get_table_statistics; | |
| 5993 | 932 | rocksdb_hton->flush_logs = rocksdb_flush_wal; | |
| 5994 | |||
| 5995 | 932 | rocksdb_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | HTON_CAN_RECREATE | | |
| 5996 | HTON_SUPPORTS_ONLINE_BACKUPS; | ||
| 5997 | |||
| 5998 | 932 | rocksdb_hton->partition_flags = rocksdb_partition_flags; | |
| 5999 | |||
| 6000 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 929 times.
|
932 | if (rocksdb_db_options->max_open_files > (long)open_files_limit) { |
| 6001 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 6002 | "rocksdb_max_open_files should not be greater than the " | ||
| 6003 | "open_files_limit, effective value of " | ||
| 6004 | "rocksdb_max_open_files is being set to open_files_limit / " | ||
| 6005 | "2."); | ||
| 6006 | 3 | rocksdb_db_options->max_open_files = open_files_limit / 2; | |
| 6007 |
2/2✓ Branch 0 taken 920 times.
✓ Branch 1 taken 9 times.
|
929 | } else if (rocksdb_db_options->max_open_files == -2) { |
| 6008 | 920 | rocksdb_db_options->max_open_files = open_files_limit / 2; | |
| 6009 | } | ||
| 6010 | |||
| 6011 |
2/4✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932 times.
✗ Branch 3 not taken.
|
932 | rdb_read_free_regex_handler.set_patterns(DEFAULT_READ_FREE_RPL_TABLES, |
| 6012 | get_regex_flags()); | ||
| 6013 | |||
| 6014 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rocksdb_stats = rocksdb::CreateDBStatistics(); |
| 6015 | 932 | rocksdb_stats->set_stats_level( | |
| 6016 | 932 | static_cast<rocksdb::StatsLevel>(rocksdb_stats_level)); | |
| 6017 | 932 | rocksdb_stats_level = rocksdb_stats->get_stats_level(); | |
| 6018 | 932 | rocksdb_db_options->statistics = rocksdb_stats; | |
| 6019 | |||
| 6020 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 928 times.
|
932 | if (rocksdb_rate_limiter_bytes_per_sec != 0) { |
| 6021 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | rocksdb_rate_limiter.reset( |
| 6022 | rocksdb::NewGenericRateLimiter(rocksdb_rate_limiter_bytes_per_sec)); | ||
| 6023 | 4 | rocksdb_db_options->rate_limiter = rocksdb_rate_limiter; | |
| 6024 | } | ||
| 6025 | |||
| 6026 | 932 | rocksdb_db_options->delayed_write_rate = rocksdb_delayed_write_rate; | |
| 6027 | |||
| 6028 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | std::shared_ptr<Rdb_logger> myrocks_logger = std::make_shared<Rdb_logger>(); |
| 6029 |
2/4✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932 times.
✗ Branch 3 not taken.
|
1864 | s = rocksdb::CreateLoggerFromOptions(rocksdb_datadir, *rocksdb_db_options, |
| 6030 | 1864 | &rocksdb_db_options->info_log); | |
| 6031 |
2/4✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932 times.
✗ Branch 3 not taken.
|
932 | if (s.ok()) { |
| 6032 | 932 | myrocks_logger->SetRocksDBLogger(rocksdb_db_options->info_log); | |
| 6033 | } | ||
| 6034 | |||
| 6035 | 932 | rocksdb_db_options->info_log = myrocks_logger; | |
| 6036 | 932 | myrocks_logger->SetInfoLogLevel( | |
| 6037 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | static_cast<rocksdb::InfoLogLevel>(rocksdb_info_log_level)); |
| 6038 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | rocksdb_db_options->wal_dir = rocksdb_wal_dir; |
| 6039 | |||
| 6040 | 1864 | rocksdb_db_options->wal_recovery_mode = | |
| 6041 | 932 | static_cast<rocksdb::WALRecoveryMode>(rocksdb_wal_recovery_mode); | |
| 6042 | |||
| 6043 | 932 | rocksdb_db_options->track_and_verify_wals_in_manifest = | |
| 6044 | rocksdb_track_and_verify_wals_in_manifest; | ||
| 6045 | |||
| 6046 | 932 | rocksdb_db_options->access_hint_on_compaction_start = | |
| 6047 | static_cast<rocksdb::Options::AccessHint>( | ||
| 6048 | rocksdb_access_hint_on_compaction_start); | ||
| 6049 | |||
| 6050 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 929 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 929 times.
|
935 | if (rocksdb_db_options->allow_mmap_reads && |
| 6051 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rocksdb_db_options->use_direct_reads) { |
| 6052 | // allow_mmap_reads implies !use_direct_reads and RocksDB will not open if | ||
| 6053 | // mmap_reads and direct_reads are both on. (NO_LINT_DEBUG) | ||
| 6054 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg( |
| 6055 | ERROR_LEVEL, 0, | ||
| 6056 | "Can't enable both use_direct_reads and allow_mmap_reads\n"); | ||
| 6057 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 6058 | } | ||
| 6059 | |||
| 6060 | // Check whether the filesystem backing rocksdb_datadir allows O_DIRECT | ||
| 6061 |
4/4✓ Branch 0 taken 926 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 920 times.
|
1855 | if (rocksdb_db_options->use_direct_reads || |
| 6062 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 920 times.
|
926 | rocksdb_db_options->use_direct_io_for_flush_and_compaction) { |
| 6063 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | rocksdb::EnvOptions soptions; |
| 6064 | 9 | rocksdb::Status check_status; | |
| 6065 | 9 | rocksdb::Env *const env = rocksdb_db_options->env; | |
| 6066 | |||
| 6067 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | std::string fname = format_string("%s/DIRECT_CHECK", rocksdb_datadir); |
| 6068 |
3/6✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
|
9 | if (env->FileExists(fname).ok()) { |
| 6069 | ✗ | std::unique_ptr<rocksdb::SequentialFile> file; | |
| 6070 | ✗ | soptions.use_direct_reads = true; | |
| 6071 | ✗ | check_status = env->NewSequentialFile(fname, &file, soptions); | |
| 6072 | ✗ | } else { | |
| 6073 | { | ||
| 6074 | 9 | std::unique_ptr<rocksdb::WritableFile> file; | |
| 6075 | 9 | soptions.use_direct_writes = true; | |
| 6076 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | check_status = env->NewWritableFile(fname, &file, soptions); |
| 6077 | 9 | } | |
| 6078 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | env->DeleteFile(fname); |
| 6079 | } | ||
| 6080 | |||
| 6081 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if (!check_status.ok()) { |
| 6082 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6083 | "Unable to use direct io in rocksdb-datadir: (%s)", | ||
| 6084 | check_status.ToString().c_str()); | ||
| 6085 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6086 | } | ||
| 6087 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | } |
| 6088 | |||
| 6089 |
2/6✓ Branch 0 taken 929 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 929 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
929 | DBUG_EXECUTE_IF("rocksdb_init_failure_reads", { |
| 6090 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 6091 | }); | ||
| 6092 | |||
| 6093 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 926 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 926 times.
|
932 | if (rocksdb_db_options->allow_mmap_writes && |
| 6094 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rocksdb_db_options->use_direct_io_for_flush_and_compaction) { |
| 6095 | // See above comment for allow_mmap_reads. (NO_LINT_DEBUG) | ||
| 6096 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 6097 | "Can't enable both use_direct_io_for_flush_and_compaction " | ||
| 6098 | "and allow_mmap_writes\n"); | ||
| 6099 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 6100 | } | ||
| 6101 | |||
| 6102 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 926 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 926 times.
|
926 | if (rocksdb_db_options->allow_mmap_writes && |
| 6103 | ✗ | rocksdb_flush_log_at_trx_commit != FLUSH_LOG_NEVER) { | |
| 6104 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6105 | "rocksdb_flush_log_at_trx_commit needs to be 0 to use " | ||
| 6106 | "allow_mmap_writes"); | ||
| 6107 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6108 | } | ||
| 6109 | |||
| 6110 | // sst_file_manager will move deleted rocksdb sst files to trash_dir | ||
| 6111 | // to be deleted in a background thread. | ||
| 6112 |
2/4✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✗ Branch 3 not taken.
|
1852 | std::string trash_dir = std::string(rocksdb_datadir) + "/trash"; |
| 6113 |
3/6✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 926 times.
✗ Branch 5 not taken.
|
1852 | rocksdb_db_options->sst_file_manager.reset(NewSstFileManager( |
| 6114 | 926 | rocksdb_db_options->env, myrocks_logger, trash_dir, | |
| 6115 | rocksdb_sst_mgr_rate_bytes_per_sec, true /* delete_existing_trash */)); | ||
| 6116 | |||
| 6117 | 926 | std::vector<std::string> cf_names; | |
| 6118 | 926 | rocksdb::Status status; | |
| 6119 |
2/4✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✗ Branch 3 not taken.
|
1852 | status = rocksdb::DB::ListColumnFamilies(*rocksdb_db_options, rocksdb_datadir, |
| 6120 | 926 | &cf_names); | |
| 6121 |
2/6✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 926 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
926 | DBUG_EXECUTE_IF("rocksdb_init_failure_list_cf", { |
| 6122 | // Simulate ListColumnFamilies failure | ||
| 6123 | status = rocksdb::Status::Corruption(); | ||
| 6124 | }); | ||
| 6125 |
3/4✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
✓ Branch 3 taken 523 times.
|
926 | if (!status.ok()) { |
| 6126 | /* | ||
| 6127 | When we start on an empty datadir, ListColumnFamilies returns IOError | ||
| 6128 | with subcode = kPathNotFound. | ||
| 6129 | */ | ||
| 6130 |
2/4✓ Branch 0 taken 403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
|
403 | if (status.IsPathNotFound()) { |
| 6131 |
9/18✓ Branch 0 taken 403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 403 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 403 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 403 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 403 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 403 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 403 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 403 times.
✗ Branch 17 not taken.
|
403 | LogPluginErrMsg( |
| 6132 | INFORMATION_LEVEL, 0, | ||
| 6133 | "Got kPathNotFound when listing column families assuming that " | ||
| 6134 | "we're creating a new database"); | ||
| 6135 | } else { | ||
| 6136 | ✗ | rdb_log_status_error(status, "Error listing column families"); | |
| 6137 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6138 | } | ||
| 6139 | } else { | ||
| 6140 |
9/18✓ Branch 0 taken 523 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 523 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 523 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 523 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 523 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 523 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 523 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 523 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 523 times.
✗ Branch 17 not taken.
|
523 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "%ld column families found", |
| 6141 | cf_names.size()); | ||
| 6142 | } | ||
| 6143 | |||
| 6144 | 926 | std::vector<rocksdb::ColumnFamilyDescriptor> cf_descr; | |
| 6145 | 926 | std::vector<rocksdb::ColumnFamilyHandle *> cf_handles; | |
| 6146 | |||
| 6147 | 1852 | rocksdb_tbl_options->index_type = | |
| 6148 | 926 | (rocksdb::BlockBasedTableOptions::IndexType)rocksdb_index_type; | |
| 6149 | |||
| 6150 |
1/2✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
|
926 | if (!rocksdb_tbl_options->no_block_cache) { |
| 6151 | 926 | std::shared_ptr<rocksdb::MemoryAllocator> memory_allocator; | |
| 6152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 926 times.
|
926 | if (!rocksdb_cache_dump) { |
| 6153 | #ifdef HAVE_JEMALLOC | ||
| 6154 | size_t block_size = rocksdb_tbl_options->block_size; | ||
| 6155 | rocksdb::JemallocAllocatorOptions alloc_opt; | ||
| 6156 | // Limit jemalloc tcache memory usage. The range | ||
| 6157 | // [block_size/4, block_size] should be enough to cover most of | ||
| 6158 | // block cache allocation sizes. | ||
| 6159 | alloc_opt.limit_tcache_size = true; | ||
| 6160 | alloc_opt.tcache_size_lower_bound = block_size / 4; | ||
| 6161 | alloc_opt.tcache_size_upper_bound = block_size; | ||
| 6162 | rocksdb::Status new_alloc_status = | ||
| 6163 | rocksdb::NewJemallocNodumpAllocator(alloc_opt, &memory_allocator); | ||
| 6164 | if (!new_alloc_status.ok()) { | ||
| 6165 | // Fallback to use default malloc/free. | ||
| 6166 | rdb_log_status_error(new_alloc_status, | ||
| 6167 | "Error excluding block cache from core dump"); | ||
| 6168 | memory_allocator = nullptr; | ||
| 6169 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 6170 | } | ||
| 6171 | #else | ||
| 6172 | // NO_LINT_DEBUG | ||
| 6173 | ✗ | LogPluginErrMsg( | |
| 6174 | WARNING_LEVEL, 0, | ||
| 6175 | "Ignoring rocksdb_cache_dump because jemalloc is missing."); | ||
| 6176 | #endif // HAVE_JEMALLOC | ||
| 6177 | } | ||
| 6178 | std::shared_ptr<rocksdb::Cache> block_cache = rocksdb::NewLRUCache( | ||
| 6179 | rocksdb_block_cache_size, -1 /*num_shard_bits*/, | ||
| 6180 | false /*strict_capcity_limit*/, rocksdb_cache_high_pri_pool_ratio, | ||
| 6181 |
1/2✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
|
926 | memory_allocator); |
| 6182 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 926 times.
|
926 | if (rocksdb_sim_cache_size > 0) { |
| 6183 | // Simulated cache enabled | ||
| 6184 | // Wrap block cache inside a simulated cache and pass it to RocksDB | ||
| 6185 | ✗ | rocksdb_tbl_options->block_cache = | |
| 6186 | ✗ | rocksdb::NewSimCache(block_cache, rocksdb_sim_cache_size, 6); | |
| 6187 | } else { | ||
| 6188 | // Pass block cache to RocksDB | ||
| 6189 | 926 | rocksdb_tbl_options->block_cache = block_cache; | |
| 6190 | } | ||
| 6191 | 926 | } | |
| 6192 | |||
| 6193 |
1/2✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
|
926 | if (rocksdb_collect_sst_properties) { |
| 6194 | properties_collector_factory = | ||
| 6195 |
1/2✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
|
926 | std::make_shared<Rdb_tbl_prop_coll_factory>(&ddl_manager); |
| 6196 | |||
| 6197 | 926 | rocksdb_set_compaction_options(nullptr, nullptr, nullptr, nullptr); | |
| 6198 | |||
| 6199 |
2/4✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✗ Branch 3 not taken.
|
926 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); |
| 6200 | |||
| 6201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 926 times.
|
926 | assert(rocksdb_table_stats_sampling_pct <= RDB_TBL_STATS_SAMPLE_PCT_MAX); |
| 6202 | 926 | properties_collector_factory->SetTableStatsSamplingPct( | |
| 6203 | rocksdb_table_stats_sampling_pct); | ||
| 6204 | |||
| 6205 |
2/4✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✗ Branch 3 not taken.
|
926 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); |
| 6206 | } | ||
| 6207 | |||
| 6208 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 914 times.
|
926 | if (rocksdb_persistent_cache_size_mb > 0) { |
| 6209 | // TODO: This is the limitations in RocksDB. | ||
| 6210 | // 1. Persistent cache size RocksDB has to be at least cache_file_size. | ||
| 6211 | // | ||
| 6212 | // utilities/persistent_cache/persistent_cache_tier.h:112 | ||
| 6213 | // Status ValidateSettings() const { | ||
| 6214 | // ... | ||
| 6215 | // if (cache_size < cache_file_size ...) { | ||
| 6216 | // ... | ||
| 6217 | // cache_file_size is set here. | ||
| 6218 | // | ||
| 6219 | // utilities/persistent_cache/persistent_cache_tier.h:165 | ||
| 6220 | // uint32_t cache_file_size = 100ULL * 1024 * 1024; | ||
| 6221 | // | ||
| 6222 | // 2. rocksdb_persistent_cache_path required persistent cache parameter | ||
| 6223 | // | ||
| 6224 | // utilities/persistent_cache/persistent_cache_tier.h:104 | ||
| 6225 | // Status ValidateSettings() const { | ||
| 6226 | // ... | ||
| 6227 | // if (!env || path.empty()) { | ||
| 6228 | // ... | ||
| 6229 | static constexpr int persistent_cache_size_mb_min = 100; | ||
| 6230 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
|
12 | if (rocksdb_persistent_cache_size_mb < persistent_cache_size_mb_min) { |
| 6231 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 6232 | "Invalid value for rocksdb_persistent_cache_size_mb. It " | ||
| 6233 | "has to be at least %i", | ||
| 6234 | persistent_cache_size_mb_min); | ||
| 6235 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 6236 | } | ||
| 6237 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
|
9 | if (!strlen(rocksdb_persistent_cache_path)) { |
| 6238 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 6239 | "Specify rocksdb_persistent_cache_size_path"); | ||
| 6240 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 6241 | } | ||
| 6242 | |||
| 6243 | 6 | std::shared_ptr<rocksdb::PersistentCache> pcache; | |
| 6244 | 6 | uint64_t cache_size_bytes = rocksdb_persistent_cache_size_mb * 1024 * 1024; | |
| 6245 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
18 | status = rocksdb::NewPersistentCache( |
| 6246 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
12 | rocksdb_db_options->env, std::string(rocksdb_persistent_cache_path), |
| 6247 | 6 | cache_size_bytes, myrocks_logger, true, &pcache); | |
| 6248 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (!status.ok()) { |
| 6249 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Persistent cache returned error: (%s)", | |
| 6250 | status.getState()); | ||
| 6251 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6252 | } | ||
| 6253 | 6 | rocksdb_tbl_options->persistent_cache = pcache; | |
| 6254 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 914 times.
|
920 | } else if (strlen(rocksdb_persistent_cache_path)) { |
| 6255 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6256 | "ust specify rocksdb_persistent_cache_size_mb"); | ||
| 6257 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6258 | } | ||
| 6259 | |||
| 6260 |
2/6✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 920 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
920 | DBUG_EXECUTE_IF("rocksdb_init_failure_cache", { |
| 6261 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 6262 | }); | ||
| 6263 | |||
| 6264 |
2/4✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 920 times.
✗ Branch 3 not taken.
|
920 | std::unique_ptr<Rdb_cf_options> cf_options_map(new Rdb_cf_options()); |
| 6265 |
2/4✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 920 times.
|
920 | if (!cf_options_map->init(*rocksdb_tbl_options, properties_collector_factory, |
| 6266 | rocksdb_default_cf_options, | ||
| 6267 | rocksdb_override_cf_options)) { | ||
| 6268 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Failed to initialize CF options map."); | |
| 6269 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6270 | } | ||
| 6271 | |||
| 6272 |
2/6✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 920 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
920 | DBUG_EXECUTE_IF("rocksdb_init_failure_cf_options", { |
| 6273 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 6274 | }); | ||
| 6275 | |||
| 6276 | /* | ||
| 6277 | If there are no column families, we're creating the new database. | ||
| 6278 | Create one column family named "default". | ||
| 6279 | */ | ||
| 6280 |
3/4✓ Branch 0 taken 403 times.
✓ Branch 1 taken 517 times.
✓ Branch 2 taken 403 times.
✗ Branch 3 not taken.
|
920 | if (cf_names.size() == 0) cf_names.push_back(DEFAULT_CF_NAME); |
| 6281 | |||
| 6282 | 920 | std::set<std::string> prev_compaction_enabled_cf_names; | |
| 6283 |
9/18✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 920 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 920 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 920 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 920 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 920 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 920 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 920 times.
✗ Branch 17 not taken.
|
920 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Column Families at start:"); |
| 6284 |
2/2✓ Branch 0 taken 2714 times.
✓ Branch 1 taken 920 times.
|
3634 | for (size_t i = 0; i < cf_names.size(); ++i) { |
| 6285 |
1/2✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
|
2714 | rocksdb::ColumnFamilyOptions opts; |
| 6286 |
1/2✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
|
2714 | cf_options_map->get_cf_options(cf_names[i], &opts); |
| 6287 | |||
| 6288 |
9/18✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2714 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2714 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2714 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2714 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2714 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2714 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2714 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2714 times.
✗ Branch 17 not taken.
|
2714 | LogPluginErrMsg(INFORMATION_LEVEL, 0, " cf=%s", cf_names[i].c_str()); |
| 6289 |
9/18✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2714 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2714 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2714 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2714 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2714 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2714 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2714 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2714 times.
✗ Branch 17 not taken.
|
2714 | LogPluginErrMsg(INFORMATION_LEVEL, 0, " write_buffer_size=%ld", |
| 6290 | opts.write_buffer_size); | ||
| 6291 |
9/18✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2714 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2714 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2714 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2714 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2714 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2714 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2714 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2714 times.
✗ Branch 17 not taken.
|
2714 | LogPluginErrMsg(INFORMATION_LEVEL, 0, " target_file_size_base=%" PRIu64, |
| 6292 | opts.target_file_size_base); | ||
| 6293 | |||
| 6294 | /* | ||
| 6295 | Temporarily disable compactions to prevent a race condition where | ||
| 6296 | compaction starts before compaction filter is ready. | ||
| 6297 | */ | ||
| 6298 |
2/2✓ Branch 0 taken 2672 times.
✓ Branch 1 taken 42 times.
|
2714 | if (!opts.disable_auto_compactions) { |
| 6299 |
1/2✓ Branch 0 taken 2672 times.
✗ Branch 1 not taken.
|
2672 | prev_compaction_enabled_cf_names.insert(cf_names[i]); |
| 6300 | 2672 | opts.disable_auto_compactions = true; | |
| 6301 | } | ||
| 6302 |
2/4✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2714 times.
✗ Branch 3 not taken.
|
2714 | cf_descr.push_back(rocksdb::ColumnFamilyDescriptor(cf_names[i], opts)); |
| 6303 | 2714 | } | |
| 6304 | |||
| 6305 | 920 | rocksdb::Options main_opts(*rocksdb_db_options, | |
| 6306 |
1/2✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
|
1840 | cf_options_map->get_defaults()); |
| 6307 | |||
| 6308 | 920 | rocksdb::TransactionDBOptions tx_db_options; | |
| 6309 | 920 | tx_db_options.transaction_lock_timeout = 2000; // 2 seconds | |
| 6310 |
1/2✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
|
920 | tx_db_options.custom_mutex_factory = std::make_shared<Rdb_mutex_factory>(); |
| 6311 | 920 | tx_db_options.write_policy = | |
| 6312 | 920 | static_cast<rocksdb::TxnDBWritePolicy>(rocksdb_write_policy); | |
| 6313 | |||
| 6314 | status = | ||
| 6315 |
1/2✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
|
920 | check_rocksdb_options_compatibility(rocksdb_datadir, main_opts, cf_descr); |
| 6316 | |||
| 6317 |
2/6✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 920 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
920 | DBUG_EXECUTE_IF("rocksdb_init_failure_incompatible_options", { |
| 6318 | // Simulate ListColumnFamilies failure | ||
| 6319 | status = rocksdb::Status::Corruption(); | ||
| 6320 | }); | ||
| 6321 | |||
| 6322 | // We won't start if we'll determine that there's a chance of data corruption | ||
| 6323 | // because of incompatible options. | ||
| 6324 |
3/4✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 917 times.
|
920 | if (!status.ok()) { |
| 6325 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rdb_log_status_error( |
| 6326 | status, "Compatibility check against existing database options failed"); | ||
| 6327 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 6328 | } | ||
| 6329 | |||
| 6330 |
9/18✓ Branch 0 taken 917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 917 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 917 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 917 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 917 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 917 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 917 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 917 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 917 times.
✗ Branch 17 not taken.
|
917 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Opening TransactionDB..."); |
| 6331 | |||
| 6332 |
2/4✓ Branch 0 taken 917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 917 times.
✗ Branch 3 not taken.
|
1834 | status = rocksdb::TransactionDB::Open( |
| 6333 | 917 | main_opts, tx_db_options, rocksdb_datadir, cf_descr, &cf_handles, &rdb); | |
| 6334 | |||
| 6335 |
2/10✓ Branch 0 taken 917 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 917 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
917 | DBUG_EXECUTE_IF("rocksdb_init_failure_open_db", { |
| 6336 | // Simulate opening TransactionDB failure | ||
| 6337 | status = rocksdb::Status::Corruption(); | ||
| 6338 | // fix a memory leak caused by not calling cf_manager.init() | ||
| 6339 | for (auto cfh_ptr : cf_handles) delete (cfh_ptr); | ||
| 6340 | }); | ||
| 6341 | |||
| 6342 |
3/4✓ Branch 0 taken 917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 902 times.
|
917 | if (!status.ok()) { |
| 6343 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | rdb_log_status_error(status, "Error opening instance"); |
| 6344 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 6345 | } | ||
| 6346 | |||
| 6347 |
9/18✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 902 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 902 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 902 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 902 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 902 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 902 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 902 times.
✗ Branch 17 not taken.
|
902 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Init column families..."); |
| 6348 |
3/6✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 902 times.
|
902 | if (st_rdb_exec_time.exec("cf_manager::init", [&]() { |
| 6349 | 902 | return cf_manager.init(rdb, std::move(cf_options_map), &cf_handles); | |
| 6350 | })) { | ||
| 6351 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Failed to init column families."); | |
| 6352 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6353 | } | ||
| 6354 | |||
| 6355 |
9/18✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 902 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 902 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 902 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 902 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 902 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 902 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 902 times.
✗ Branch 17 not taken.
|
902 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Initializing data dictionary..."); |
| 6356 |
3/6✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 902 times.
|
902 | if (st_rdb_exec_time.exec("Rdb_dict_manager_selector::init", [&]() { |
| 6357 | 902 | return dict_manager.init(rdb, &cf_manager, | |
| 6358 | 902 | rocksdb_enable_remove_orphaned_dropped_cfs); | |
| 6359 | })) { | ||
| 6360 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Failed to initialize data dictionary."); | |
| 6361 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6362 | } | ||
| 6363 | |||
| 6364 |
9/18✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 902 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 902 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 902 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 902 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 902 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 902 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 902 times.
✗ Branch 17 not taken.
|
902 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "Initializing DDL Manager..."); |
| 6365 |
3/6✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 902 times.
|
902 | if (st_rdb_exec_time.exec("Rdb_ddl_manager::init", [&]() { |
| 6366 | #if defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 6367 | 902 | return ddl_manager.init(&dict_manager, &cf_manager, | |
| 6368 | 902 | rocksdb_validate_tables); | |
| 6369 | #else | ||
| 6370 | return ddl_manager.init(&dict_manager, &cf_manager); | ||
| 6371 | #endif // defined(ROCKSDB_INCLUDE_VALIDATE_TABLES) && | ||
| 6372 | // ROCKSDB_INCLUDE_VALIDATE_TABLES | ||
| 6373 | })) { | ||
| 6374 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Failed to initialize DDL manager."); | |
| 6375 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6376 | } | ||
| 6377 | |||
| 6378 |
3/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3043 times.
✓ Branch 3 taken 902 times.
|
3945 | for (const auto &cf_handle : cf_manager.get_all_cf()) { |
| 6379 | uint flags; | ||
| 6380 |
1/2✓ Branch 0 taken 3043 times.
✗ Branch 1 not taken.
|
3043 | auto local_dict_manager = dict_manager.get_dict_manager_selector_non_const( |
| 6381 | false /*is_tmp_table*/); | ||
| 6382 |
3/6✓ Branch 0 taken 3043 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3043 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3043 times.
|
3043 | if (!local_dict_manager->get_cf_flags(cf_handle->GetID(), &flags)) { |
| 6383 | const std::unique_ptr<rocksdb::WriteBatch> wb = | ||
| 6384 | ✗ | local_dict_manager->begin(); | |
| 6385 | ✗ | rocksdb::WriteBatch *const batch = wb.get(); | |
| 6386 | ✗ | local_dict_manager->add_cf_flags(batch, cf_handle->GetID(), 0); | |
| 6387 | ✗ | local_dict_manager->commit(batch); | |
| 6388 | } | ||
| 6389 | 902 | } | |
| 6390 | |||
| 6391 |
2/6✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 902 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
902 | DBUG_EXECUTE_IF("rocksdb_init_failure_managers", |
| 6392 | { DBUG_RETURN(HA_EXIT_FAILURE); }); | ||
| 6393 | |||
| 6394 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | Rdb_sst_info::init(rdb); |
| 6395 | |||
| 6396 | /* | ||
| 6397 | Enable auto compaction, things needed for compaction filter are finished | ||
| 6398 | initializing | ||
| 6399 | */ | ||
| 6400 | 902 | std::vector<rocksdb::ColumnFamilyHandle *> new_compaction_enabled_cf_handles; | |
| 6401 |
2/2✓ Branch 0 taken 3043 times.
✓ Branch 1 taken 902 times.
|
3945 | for (auto cfh_ptr : cf_handles) { |
| 6402 |
2/4✓ Branch 0 taken 3043 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3043 times.
✗ Branch 3 not taken.
|
3043 | if (prev_compaction_enabled_cf_names.find(cfh_ptr->GetName()) != |
| 6403 |
2/2✓ Branch 0 taken 2592 times.
✓ Branch 1 taken 451 times.
|
6086 | prev_compaction_enabled_cf_names.end()) { |
| 6404 |
1/2✓ Branch 0 taken 2592 times.
✗ Branch 1 not taken.
|
2592 | new_compaction_enabled_cf_handles.push_back(cfh_ptr); |
| 6405 | } | ||
| 6406 | } | ||
| 6407 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | status = rdb->EnableAutoCompaction(new_compaction_enabled_cf_handles); |
| 6408 | |||
| 6409 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 902 times.
|
902 | if (!status.ok()) { |
| 6410 | ✗ | rdb_log_status_error(status, "Error enabling compaction"); | |
| 6411 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6412 | } | ||
| 6413 | |||
| 6414 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
|
902 | auto err = rdb_bg_thread.create_thread(BG_THREAD_NAME |
| 6415 | #ifdef HAVE_PSI_INTERFACE | ||
| 6416 | , | ||
| 6417 | rdb_background_psi_thread_key | ||
| 6418 | #endif | ||
| 6419 | ); | ||
| 6420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 902 times.
|
902 | if (err != 0) { |
| 6421 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6422 | "Couldn't start the background thread: (errno=%d)", err); | ||
| 6423 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6424 | } | ||
| 6425 | |||
| 6426 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
|
902 | err = rdb_drop_idx_thread.create_thread(INDEX_THREAD_NAME |
| 6427 | #ifdef HAVE_PSI_INTERFACE | ||
| 6428 | , | ||
| 6429 | rdb_drop_idx_psi_thread_key | ||
| 6430 | #endif | ||
| 6431 | ); | ||
| 6432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 902 times.
|
902 | if (err != 0) { |
| 6433 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6434 | "Couldn't start the drop index thread: (errno=%d)", err); | ||
| 6435 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6436 | } | ||
| 6437 | |||
| 6438 | #ifndef HAVE_PSI_INTERFACE | ||
| 6439 | err = rdb_is_thread.create_thread(INDEX_STATS_THREAD_NAME); | ||
| 6440 | #else | ||
| 6441 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
|
902 | err = rdb_is_thread.create_thread(INDEX_STATS_THREAD_NAME, |
| 6442 | rdb_is_psi_thread_key); | ||
| 6443 | #endif | ||
| 6444 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 902 times.
|
902 | if (err != 0) { |
| 6445 | ✗ | LogPluginErrMsg( | |
| 6446 | ERROR_LEVEL, 0, | ||
| 6447 | "Couldn't start the index stats calculation thread: (errno=%d)", err); | ||
| 6448 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6449 | } | ||
| 6450 | |||
| 6451 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
|
902 | err = rdb_mc_thread.create_thread(MANUAL_COMPACTION_THREAD_NAME |
| 6452 | #ifdef HAVE_PSI_INTERFACE | ||
| 6453 | , | ||
| 6454 | rdb_mc_psi_thread_key | ||
| 6455 | #endif | ||
| 6456 | ); | ||
| 6457 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 902 times.
|
902 | if (err != 0) { |
| 6458 | // NO_LINT_DEBUG | ||
| 6459 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6460 | "Couldn't start the manual compaction thread: (errno=%d)", | ||
| 6461 | err); | ||
| 6462 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6463 | } | ||
| 6464 | |||
| 6465 |
2/6✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 902 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
902 | DBUG_EXECUTE_IF("rocksdb_init_failure_threads", |
| 6466 | { DBUG_RETURN(HA_EXIT_FAILURE); }); | ||
| 6467 | |||
| 6468 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | rdb_set_collation_exception_list(rocksdb_strict_collation_exceptions); |
| 6469 | |||
| 6470 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 902 times.
|
902 | if (rocksdb_pause_background_work) { |
| 6471 | ✗ | rdb->PauseBackgroundWork(); | |
| 6472 | } | ||
| 6473 | |||
| 6474 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | err = my_error_register(rdb_get_error_messages, HA_ERR_ROCKSDB_FIRST, |
| 6475 | HA_ERR_ROCKSDB_LAST); | ||
| 6476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 902 times.
|
902 | if (err != 0) { |
| 6477 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Couldn't initialize error messages"); | |
| 6478 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 6479 | } | ||
| 6480 | |||
| 6481 | // Creating an instance of HistogramImpl should only happen after RocksDB | ||
| 6482 | // has been successfully initialized. | ||
| 6483 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
|
902 | commit_latency_stats = new rocksdb::HistogramImpl(); |
| 6484 | |||
| 6485 | // succeeded, set the init status flag | ||
| 6486 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | rdb_get_hton_init_state()->set_initialized(true); |
| 6487 | |||
| 6488 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | compaction_stats.resize_history(rocksdb_max_compaction_history); |
| 6489 | |||
| 6490 | // Remove tables that may have been leftover during truncation | ||
| 6491 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | rocksdb_truncation_table_cleanup(); |
| 6492 | |||
| 6493 | // NO_LINT_DEBUG | ||
| 6494 |
9/18✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 902 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 902 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 902 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 902 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 902 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 902 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 902 times.
✗ Branch 17 not taken.
|
902 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 6495 | "MyRocks storage engine plugin has been successfully " | ||
| 6496 | "initialized."); | ||
| 6497 | |||
| 6498 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | st_rdb_exec_time.report(); |
| 6499 | |||
| 6500 | // Skip cleaning up rdb_open_tables as we've succeeded | ||
| 6501 | 902 | rdb_open_tables_cleanup.skip(); | |
| 6502 | |||
| 6503 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | rocksdb_set_max_bottom_pri_background_compactions_internal( |
| 6504 | rocksdb_max_bottom_pri_background_compactions); | ||
| 6505 | |||
| 6506 |
2/6✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 902 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
902 | DBUG_EXECUTE_IF("rocksdb_init_failure_everything_initialized", |
| 6507 | { DBUG_RETURN(HA_EXIT_FAILURE); }); | ||
| 6508 | |||
| 6509 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 6510 | 935 | } | |
| 6511 | |||
| 6512 | // This function cleans up after both normal and init-failure scenarios. | ||
| 6513 | // It can be unsafe to perform some cleanup after initalization failure, | ||
| 6514 | // so currently only some code is executed for such scenarios. | ||
| 6515 | // More code will be safeguarded and executed for both scenarios, and | ||
| 6516 | // eventually minimalShutdown parameter will be removed (always = false). | ||
| 6517 | // @parameter minimalShutdown - only perform uninitialization deemed safe | ||
| 6518 | // (experimentation). | ||
| 6519 | 899 | static int rocksdb_shutdown(bool minimalShutdown) { | |
| 6520 | 899 | int error = 0; | |
| 6521 | |||
| 6522 | // If we finalize the storage engine plugin, it is no longer initialized. | ||
| 6523 | // Grab a writer lock for the duration of the call, so we can clear the flag | ||
| 6524 | // and destroy the handlerton and global state in isolation. | ||
| 6525 |
2/4✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 899 times.
✗ Branch 3 not taken.
|
899 | Rdb_hton_init_state::Scoped_lock state_lock(*rdb_get_hton_init_state(), true); |
| 6526 | |||
| 6527 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | if (!minimalShutdown) { |
| 6528 | // signal the drop index thread to stop | ||
| 6529 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_drop_idx_thread.signal(true); |
| 6530 | |||
| 6531 | // Flush all memtables for not losing data, even if WAL is disabled. | ||
| 6532 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rocksdb_flush_all_memtables(); |
| 6533 | |||
| 6534 | // Stop all rocksdb background work | ||
| 6535 |
6/8✓ Branch 0 taken 866 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 866 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 866 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 866 times.
✓ Branch 7 taken 33 times.
|
899 | if (rdb && rdb->GetBaseDB()) { |
| 6536 |
2/4✓ Branch 0 taken 866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 866 times.
✗ Branch 3 not taken.
|
866 | CancelAllBackgroundWork(rdb->GetBaseDB(), true); |
| 6537 | } | ||
| 6538 | |||
| 6539 | // Signal the background thread to stop and to persist all stats collected | ||
| 6540 | // from background flushes and compactions. This will add more keys to a new | ||
| 6541 | // memtable, but since the memtables were just flushed, it should not | ||
| 6542 | // trigger a flush that can stall due to background threads being stopped. | ||
| 6543 | // As long as these keys are stored in a WAL file, they can be retrieved on | ||
| 6544 | // restart. | ||
| 6545 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_bg_thread.signal(true); |
| 6546 | |||
| 6547 | // signal the index stats calculation thread to stop | ||
| 6548 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_is_thread.signal(true); |
| 6549 | |||
| 6550 | // signal the manual compaction thread to stop | ||
| 6551 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_mc_thread.signal(true); |
| 6552 | |||
| 6553 | // Wait for the background thread to finish. | ||
| 6554 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | auto err = rdb_bg_thread.join(); |
| 6555 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 866 times.
|
899 | if (err != 0) { |
| 6556 | // We'll log the message and continue because we're shutting down and | ||
| 6557 | // continuation is the optimal strategy. | ||
| 6558 |
9/18✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 33 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 33 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 33 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 33 times.
✗ Branch 17 not taken.
|
33 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 6559 | "Couldn't stop the background thread: (errno=%d)", err); | ||
| 6560 | } | ||
| 6561 | |||
| 6562 | // Wait for the drop index thread to finish. | ||
| 6563 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | err = rdb_drop_idx_thread.join(); |
| 6564 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 866 times.
|
899 | if (err != 0) { |
| 6565 |
9/18✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 33 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 33 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 33 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 33 times.
✗ Branch 17 not taken.
|
33 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 6566 | "Couldn't stop the index thread: (errno=%d)", err); | ||
| 6567 | } | ||
| 6568 | |||
| 6569 | // Wait for the index stats calculation thread to finish. | ||
| 6570 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | err = rdb_is_thread.join(); |
| 6571 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 866 times.
|
899 | if (err != 0) { |
| 6572 |
9/18✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 33 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 33 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 33 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 33 times.
✗ Branch 17 not taken.
|
33 | LogPluginErrMsg( |
| 6573 | ERROR_LEVEL, 0, | ||
| 6574 | "Couldn't stop the index stats calculation thread: (errno=%d)", err); | ||
| 6575 | } | ||
| 6576 | |||
| 6577 | // Wait for the manual compaction thread to finish. | ||
| 6578 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | err = rdb_mc_thread.join(); |
| 6579 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 866 times.
|
899 | if (err != 0) { |
| 6580 |
9/18✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 33 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 33 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 33 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 33 times.
✗ Branch 17 not taken.
|
33 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 6581 | "Couldn't stop the manual compaction thread: (errno=%d)", | ||
| 6582 | err); | ||
| 6583 | } | ||
| 6584 | |||
| 6585 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 899 times.
|
899 | if (rdb_open_tables.count()) { |
| 6586 | // Looks like we are getting unloaded and yet we have some open tables | ||
| 6587 | // left behind. | ||
| 6588 | |||
| 6589 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 6590 | "There're tables still opened during shutdown"); | ||
| 6591 | ✗ | error = 1; | |
| 6592 | } | ||
| 6593 | |||
| 6594 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_open_tables.free(); |
| 6595 | } | ||
| 6596 | |||
| 6597 | // The only code executed during both normal and init faiure shutdown are | ||
| 6598 | // deleting mutexes. The plan is to gradually increase this section so there's | ||
| 6599 | // one single shutdown function for all scenarios. | ||
| 6600 | |||
| 6601 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_sysvars_mutex.destroy(); |
| 6602 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_block_cache_resize_mutex.destroy(); |
| 6603 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_bottom_pri_background_compactions_resize_mutex.destroy(); |
| 6604 | |||
| 6605 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | if (!minimalShutdown) { |
| 6606 |
2/2✓ Branch 0 taken 896 times.
✓ Branch 1 taken 3 times.
|
899 | delete rdb_collation_exceptions; |
| 6607 | 899 | rdb_collation_exceptions = nullptr; | |
| 6608 | } | ||
| 6609 | |||
| 6610 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_collation_data_mutex.destroy(); |
| 6611 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_mem_cmp_space_mutex.destroy(); |
| 6612 | |||
| 6613 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | Rdb_transaction::term_mutex(); |
| 6614 | |||
| 6615 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | if (!minimalShutdown) { |
| 6616 |
2/2✓ Branch 0 taken 1841152 times.
✓ Branch 1 taken 899 times.
|
1842051 | for (auto &it : rdb_collation_data) { |
| 6617 |
2/2✓ Branch 0 taken 200 times.
✓ Branch 1 taken 1840952 times.
|
1841152 | delete it; |
| 6618 | 1841152 | it = nullptr; | |
| 6619 | } | ||
| 6620 | |||
| 6621 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | ddl_manager.cleanup(); |
| 6622 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | dict_manager.cleanup(); |
| 6623 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | cf_manager.cleanup(); |
| 6624 | |||
| 6625 |
2/2✓ Branch 0 taken 866 times.
✓ Branch 1 taken 33 times.
|
899 | delete rdb; |
| 6626 | 899 | rdb = nullptr; | |
| 6627 | |||
| 6628 |
2/2✓ Branch 0 taken 866 times.
✓ Branch 1 taken 33 times.
|
899 | delete commit_latency_stats; |
| 6629 | 899 | commit_latency_stats = nullptr; | |
| 6630 | |||
| 6631 | // Disown the cache data since we're shutting down. | ||
| 6632 | // This results in memory leaks but it improved the shutdown time. | ||
| 6633 | // Don't disown when running under valgrind | ||
| 6634 | #ifndef HAVE_VALGRIND | ||
| 6635 |
2/2✓ Branch 0 taken 890 times.
✓ Branch 1 taken 9 times.
|
899 | if (rocksdb_tbl_options->block_cache) { |
| 6636 |
1/2✓ Branch 0 taken 890 times.
✗ Branch 1 not taken.
|
890 | rocksdb_tbl_options->block_cache->DisownData(); |
| 6637 | } | ||
| 6638 | #endif /* HAVE_VALGRIND */ | ||
| 6639 | } | ||
| 6640 | |||
| 6641 | 899 | rocksdb_db_options = nullptr; | |
| 6642 | 899 | rocksdb_tbl_options = nullptr; | |
| 6643 | 899 | rocksdb_stats = nullptr; | |
| 6644 | |||
| 6645 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | if (!minimalShutdown) { |
| 6646 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | my_error_unregister(HA_ERR_ROCKSDB_FIRST, HA_ERR_ROCKSDB_LAST); |
| 6647 | } | ||
| 6648 | |||
| 6649 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | deinit_logging_service_for_plugin(®_srv, &log_bi, &log_bs); |
| 6650 | |||
| 6651 | // clear the initialized flag and unlock | ||
| 6652 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | rdb_get_hton_init_state()->set_initialized(false); |
| 6653 | |||
| 6654 | 899 | return error; | |
| 6655 | 899 | } | |
| 6656 | |||
| 6657 | /* | ||
| 6658 | Storage Engine deinitialization function, invoked when plugin is unloaded. | ||
| 6659 | */ | ||
| 6660 | |||
| 6661 | 899 | static int rocksdb_done_func(void *const p MY_ATTRIBUTE((__unused__))) { | |
| 6662 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | DBUG_ENTER_FUNC(); |
| 6663 | |||
| 6664 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | int error = rocksdb_shutdown(/* minimalShutdown = */ false); |
| 6665 | |||
| 6666 |
1/2✓ Branch 0 taken 899 times.
✗ Branch 1 not taken.
|
899 | DBUG_RETURN(error); |
| 6667 | } | ||
| 6668 | |||
| 6669 | 935 | static int rocksdb_init_func(void *const p) { | |
| 6670 | 935 | int ret = rocksdb_init_internal(p); | |
| 6671 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 902 times.
|
935 | if (ret) { |
| 6672 | 33 | rocksdb_done_func(p); | |
| 6673 | } | ||
| 6674 | 935 | return ret; | |
| 6675 | } | ||
| 6676 | |||
| 6677 | // If the iterator is not valid it might be because of EOF but might be due | ||
| 6678 | // to IOError or corruption. The good practice is always check it. | ||
| 6679 | // https://github.com/facebook/rocksdb/wiki/Iterator#error-handling | ||
| 6680 | 197093181 | bool is_valid_iterator(rocksdb::Iterator *scan_it) { | |
| 6681 |
2/2✓ Branch 0 taken 196840575 times.
✓ Branch 1 taken 252606 times.
|
197093181 | if (scan_it->Valid()) { |
| 6682 | 196840575 | return true; | |
| 6683 | } else { | ||
| 6684 |
1/2✓ Branch 0 taken 252606 times.
✗ Branch 1 not taken.
|
252606 | rocksdb::Status s = scan_it->status(); |
| 6685 |
2/6✓ Branch 0 taken 252606 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 252606 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
252606 | DBUG_EXECUTE_IF("rocksdb_return_status_corrupted", |
| 6686 | dbug_change_status_to_corrupted(&s);); | ||
| 6687 |
5/10✓ Branch 0 taken 252606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 252606 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 252606 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 252606 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 252606 times.
|
252606 | if (s.IsIOError() || s.IsCorruption()) { |
| 6688 | ✗ | if (s.IsCorruption()) { | |
| 6689 | ✗ | rdb_persist_corruption_marker(); | |
| 6690 | } | ||
| 6691 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_GENERAL); | |
| 6692 | } | ||
| 6693 | 252606 | return false; | |
| 6694 | 252606 | } | |
| 6695 | } | ||
| 6696 | |||
| 6697 | /** | ||
| 6698 | @brief | ||
| 6699 | Example of simple lock controls. The "table_handler" it creates is a | ||
| 6700 | structure we will pass to each ha_rocksdb handler. Do you have to have | ||
| 6701 | one of these? Well, you have pieces that are used for locking, and | ||
| 6702 | they are needed to function. | ||
| 6703 | */ | ||
| 6704 | |||
| 6705 | 24070 | Rdb_table_handler *Rdb_open_tables_map::get_table_handler( | |
| 6706 | const char *const table_name) { | ||
| 6707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24070 times.
|
24070 | assert(table_name != nullptr); |
| 6708 | |||
| 6709 | Rdb_table_handler *table_handler; | ||
| 6710 | |||
| 6711 |
1/2✓ Branch 0 taken 24070 times.
✗ Branch 1 not taken.
|
24070 | const std::string table_name_str(table_name); |
| 6712 | |||
| 6713 | // First, look up the table in the hash map. | ||
| 6714 |
2/4✓ Branch 0 taken 24070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24070 times.
✗ Branch 3 not taken.
|
24070 | RDB_MUTEX_LOCK_CHECK(m_mutex); |
| 6715 |
1/2✓ Branch 0 taken 24070 times.
✗ Branch 1 not taken.
|
24070 | const auto &it = m_table_map.find(table_name_str); |
| 6716 |
2/2✓ Branch 0 taken 6149 times.
✓ Branch 1 taken 17921 times.
|
24070 | if (it != m_table_map.end()) { |
| 6717 | // Found it | ||
| 6718 | 6149 | table_handler = it->second; | |
| 6719 | } else { | ||
| 6720 | char *tmp_name; | ||
| 6721 | |||
| 6722 | // Since we did not find it in the hash map, attempt to create and add it | ||
| 6723 | // to the hash map. | ||
| 6724 | #ifdef HAVE_PSI_INTERFACE | ||
| 6725 | 17921 | if (!(table_handler = reinterpret_cast<Rdb_table_handler *>( | |
| 6726 |
2/4✓ Branch 0 taken 17921 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17921 times.
|
17921 | my_multi_malloc(rdb_handler_memory_key, MYF(MY_WME | MY_ZEROFILL), |
| 6727 | &table_handler, sizeof(*table_handler), &tmp_name, | ||
| 6728 | 17921 | table_name_str.length() + 1, NullS)))) { | |
| 6729 | #else | ||
| 6730 | if (!(table_handler = reinterpret_cast<Rdb_table_handler *>( | ||
| 6731 | my_multi_malloc(PSI_NOT_INSTRUMENTED, MYF(MY_WME | MY_ZEROFILL), | ||
| 6732 | &table_handler, sizeof(*table_handler), &tmp_name, | ||
| 6733 | table_name_str.length() + 1, NullS)))) { | ||
| 6734 | #endif | ||
| 6735 | // Allocating a new Rdb_table_handler and a new table name failed. | ||
| 6736 | ✗ | RDB_MUTEX_UNLOCK_CHECK(m_mutex); | |
| 6737 | ✗ | return nullptr; | |
| 6738 | } | ||
| 6739 | |||
| 6740 | 17921 | table_handler->m_ref_count = 0; | |
| 6741 | 17921 | table_handler->m_table_name_length = table_name_str.length(); | |
| 6742 | 17921 | table_handler->m_table_name = tmp_name; | |
| 6743 | 17921 | my_stpmov(table_handler->m_table_name, table_name_str.c_str()); | |
| 6744 | |||
| 6745 |
1/2✓ Branch 0 taken 17921 times.
✗ Branch 1 not taken.
|
17921 | m_table_map.emplace(table_name_str, table_handler); |
| 6746 | |||
| 6747 |
1/2✓ Branch 0 taken 17921 times.
✗ Branch 1 not taken.
|
17921 | thr_lock_init(&table_handler->m_thr_lock); |
| 6748 |
1/2✓ Branch 0 taken 17921 times.
✗ Branch 1 not taken.
|
17921 | table_handler->m_io_perf_read.init(); |
| 6749 | } | ||
| 6750 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24070 times.
|
24070 | assert(table_handler->m_ref_count >= 0); |
| 6751 | 24070 | table_handler->m_ref_count++; | |
| 6752 | |||
| 6753 |
2/4✓ Branch 0 taken 24070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24070 times.
✗ Branch 3 not taken.
|
24070 | RDB_MUTEX_UNLOCK_CHECK(m_mutex); |
| 6754 | |||
| 6755 | 24070 | return table_handler; | |
| 6756 | 24070 | } | |
| 6757 | |||
| 6758 | 33 | std::vector<std::string> rdb_get_open_table_names(void) { | |
| 6759 | 33 | return rdb_open_tables.get_table_names(); | |
| 6760 | } | ||
| 6761 | |||
| 6762 | 33 | std::vector<std::string> Rdb_open_tables_map::get_table_names(void) const { | |
| 6763 | const Rdb_table_handler *table_handler; | ||
| 6764 | 33 | std::vector<std::string> names; | |
| 6765 | |||
| 6766 |
2/4✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
|
33 | RDB_MUTEX_LOCK_CHECK(m_mutex); |
| 6767 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 33 times.
|
87 | for (const auto &kv : m_table_map) { |
| 6768 | 54 | table_handler = kv.second; | |
| 6769 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | assert(table_handler != nullptr); |
| 6770 |
2/4✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
54 | names.push_back(table_handler->m_table_name); |
| 6771 | } | ||
| 6772 |
2/4✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
|
33 | RDB_MUTEX_UNLOCK_CHECK(m_mutex); |
| 6773 | |||
| 6774 | 33 | return names; | |
| 6775 | } | ||
| 6776 | |||
| 6777 | /* | ||
| 6778 | Inspired by innobase_get_int_col_max_value from InnoDB. This returns the | ||
| 6779 | maximum value a type can take on. | ||
| 6780 | */ | ||
| 6781 | 14843455 | static ulonglong rdb_get_int_col_max_value(const Field *field) { | |
| 6782 | 14843455 | ulonglong max_value = 0; | |
| 6783 |
9/13✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 95 times.
✓ Branch 6 taken 436 times.
✓ Branch 7 taken 14604202 times.
✓ Branch 8 taken 144 times.
✓ Branch 9 taken 251465 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 5490 times.
|
14843455 | switch (field->key_type()) { |
| 6784 | ✗ | case HA_KEYTYPE_BINARY: | |
| 6785 | ✗ | max_value = 0xFFULL; | |
| 6786 | ✗ | break; | |
| 6787 | 24 | case HA_KEYTYPE_INT8: | |
| 6788 | 24 | max_value = 0x7FULL; | |
| 6789 | 24 | break; | |
| 6790 | ✗ | case HA_KEYTYPE_USHORT_INT: | |
| 6791 | ✗ | max_value = 0xFFFFULL; | |
| 6792 | ✗ | break; | |
| 6793 | 60 | case HA_KEYTYPE_SHORT_INT: | |
| 6794 | 60 | max_value = 0x7FFFULL; | |
| 6795 | 60 | break; | |
| 6796 | ✗ | case HA_KEYTYPE_UINT24: | |
| 6797 | ✗ | max_value = 0xFFFFFFULL; | |
| 6798 | ✗ | break; | |
| 6799 | 95 | case HA_KEYTYPE_INT24: | |
| 6800 | 95 | max_value = 0x7FFFFFULL; | |
| 6801 | 95 | break; | |
| 6802 | 436 | case HA_KEYTYPE_ULONG_INT: | |
| 6803 | 436 | max_value = 0xFFFFFFFFULL; | |
| 6804 | 436 | break; | |
| 6805 | 14604202 | case HA_KEYTYPE_LONG_INT: | |
| 6806 | 14604202 | max_value = 0x7FFFFFFFULL; | |
| 6807 | 14604202 | break; | |
| 6808 | 144 | case HA_KEYTYPE_ULONGLONG: | |
| 6809 | 144 | max_value = 0xFFFFFFFFFFFFFFFFULL; | |
| 6810 | 144 | break; | |
| 6811 | 251465 | case HA_KEYTYPE_LONGLONG: | |
| 6812 | 251465 | max_value = 0x7FFFFFFFFFFFFFFFULL; | |
| 6813 | 251465 | break; | |
| 6814 | ✗ | case HA_KEYTYPE_FLOAT: | |
| 6815 | ✗ | max_value = 0x1000000ULL; | |
| 6816 | ✗ | break; | |
| 6817 | 3 | case HA_KEYTYPE_DOUBLE: | |
| 6818 | 3 | max_value = 0x20000000000000ULL; | |
| 6819 | 3 | break; | |
| 6820 | 5490 | default: | |
| 6821 | 5490 | abort(); | |
| 6822 | } | ||
| 6823 | |||
| 6824 | 14856429 | return max_value; | |
| 6825 | } | ||
| 6826 | |||
| 6827 | 2068 | void ha_rocksdb::load_auto_incr_value() { | |
| 6828 | 2068 | ulonglong auto_incr = 0; | |
| 6829 | 2068 | bool validate_last = false, use_datadic = true; | |
| 6830 | #if !defined(NDEBUG) | ||
| 6831 |
3/4✓ Branch 0 taken 2068 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2065 times.
|
2068 | DBUG_EXECUTE_IF("myrocks_autoinc_upgrade", use_datadic = false;); |
| 6832 | 2068 | validate_last = true; | |
| 6833 | #endif // !defined(NDEBUG) | ||
| 6834 | |||
| 6835 |
2/2✓ Branch 0 taken 2065 times.
✓ Branch 1 taken 3 times.
|
4133 | if (use_datadic && |
| 6836 | dict_manager | ||
| 6837 | .get_dict_manager_selector_const( | ||
| 6838 |
1/2✓ Branch 0 taken 2065 times.
✗ Branch 1 not taken.
|
2065 | m_tbl_def->get_autoincr_gl_index_id().cf_id) |
| 6839 |
7/10✓ Branch 0 taken 2065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2065 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2065 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 431 times.
✓ Branch 7 taken 1634 times.
✓ Branch 8 taken 431 times.
✓ Branch 9 taken 1637 times.
|
4133 | ->get_auto_incr_val(m_tbl_def->get_autoincr_gl_index_id(), |
| 6840 | &auto_incr)) { | ||
| 6841 |
1/2✓ Branch 0 taken 431 times.
✗ Branch 1 not taken.
|
431 | update_auto_incr_val(auto_incr); |
| 6842 | } | ||
| 6843 | |||
| 6844 | // If we find nothing in the data dictionary, or if we are in debug mode, | ||
| 6845 | // then call index_last to get the last value. | ||
| 6846 | // | ||
| 6847 | // This is needed when upgrading from a server that did not support | ||
| 6848 | // persistent auto_increment, of if the table is empty. | ||
| 6849 | // | ||
| 6850 | // For debug mode, we are just verifying that the data dictionary value is | ||
| 6851 | // greater than or equal to the maximum value in the table. | ||
| 6852 |
3/4✓ Branch 0 taken 431 times.
✓ Branch 1 taken 1637 times.
✓ Branch 2 taken 431 times.
✗ Branch 3 not taken.
|
2068 | if (auto_incr == 0 || validate_last) { |
| 6853 |
1/2✓ Branch 0 taken 2068 times.
✗ Branch 1 not taken.
|
2068 | auto_incr = load_auto_incr_value_from_index(); |
| 6854 |
1/2✓ Branch 0 taken 2068 times.
✗ Branch 1 not taken.
|
2068 | update_auto_incr_val(auto_incr); |
| 6855 | } | ||
| 6856 | |||
| 6857 | // If we failed to find anything from the data dictionary and index, then | ||
| 6858 | // initialize auto_increment to 1. | ||
| 6859 |
2/2✓ Branch 0 taken 1626 times.
✓ Branch 1 taken 442 times.
|
2068 | if (m_tbl_def->m_auto_incr_val == 0) { |
| 6860 |
1/2✓ Branch 0 taken 1626 times.
✗ Branch 1 not taken.
|
1626 | update_auto_incr_val(1); |
| 6861 | } | ||
| 6862 | 2068 | } | |
| 6863 | |||
| 6864 | 2155 | ulonglong ha_rocksdb::load_auto_incr_value_from_index() { | |
| 6865 | 2155 | const int save_active_index = active_index; | |
| 6866 | 2155 | active_index = table->s->next_number_index; | |
| 6867 | |||
| 6868 |
2/4✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2155 times.
|
2155 | assert(!m_key_descr_arr[active_index_pos()]->is_partial_index()); |
| 6869 | std::unique_ptr<Rdb_iterator> save_iterator(new Rdb_iterator_base( | ||
| 6870 |
4/8✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2155 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2155 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2155 times.
✗ Branch 7 not taken.
|
4310 | ha_thd(), m_key_descr_arr[active_index_pos()], m_pk_descr, m_tbl_def)); |
| 6871 | 2155 | std::swap(m_iterator, save_iterator); | |
| 6872 | |||
| 6873 | 2155 | ulonglong last_val = 0; | |
| 6874 | |||
| 6875 |
1/2✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
|
2155 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); |
| 6876 | 2155 | const bool is_new_snapshot = !tx->has_snapshot(); | |
| 6877 |
1/2✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
|
2155 | if (is_new_snapshot) { |
| 6878 |
1/2✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
|
2155 | tx->acquire_snapshot(true); |
| 6879 | } | ||
| 6880 | |||
| 6881 | // Do a lookup. We only need index column, so it should be index-only. | ||
| 6882 | // (another reason to make it index-only is that table->read_set is not set | ||
| 6883 | // appropriately and non-index-only lookup will not read the value) | ||
| 6884 | 2155 | const bool save_keyread_only = m_keyread_only; | |
| 6885 | 2155 | m_keyread_only = true; | |
| 6886 | 2155 | m_converter->set_is_key_requested(true); | |
| 6887 | |||
| 6888 |
3/4✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 413 times.
✓ Branch 3 taken 1742 times.
|
2155 | if (!index_last(table->record[0])) { |
| 6889 | 413 | Field *field = | |
| 6890 | 413 | table->key_info[table->s->next_number_index].key_part[0].field; | |
| 6891 |
1/2✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
|
413 | ulonglong max_val = rdb_get_int_col_max_value(field); |
| 6892 | my_bitmap_map *const old_map = | ||
| 6893 | 413 | dbug_tmp_use_all_columns(table, table->read_set); | |
| 6894 |
1/2✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
|
413 | last_val = field->val_int(); |
| 6895 |
1/2✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
|
413 | if (last_val != max_val) { |
| 6896 | 413 | last_val++; | |
| 6897 | } | ||
| 6898 | #ifndef NDEBUG | ||
| 6899 | ulonglong dd_val; | ||
| 6900 |
1/2✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
|
413 | if (last_val <= max_val) { |
| 6901 |
1/2✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
|
413 | const auto &gl_index_id = m_tbl_def->get_autoincr_gl_index_id(); |
| 6902 | 826 | if (dict_manager.get_dict_manager_selector_const(gl_index_id.cf_id) | |
| 6903 |
6/8✓ Branch 0 taken 413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 413 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 410 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 410 times.
✓ Branch 7 taken 3 times.
|
823 | ->get_auto_incr_val(gl_index_id, &dd_val) && |
| 6904 |
2/4✓ Branch 0 taken 410 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 410 times.
✗ Branch 3 not taken.
|
410 | tx->get_auto_incr(gl_index_id) == 0) { |
| 6905 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 410 times.
|
410 | assert(dd_val >= last_val); |
| 6906 | } | ||
| 6907 | } | ||
| 6908 | #endif | ||
| 6909 | 413 | dbug_tmp_restore_column_map(table->read_set, old_map); | |
| 6910 | } | ||
| 6911 | |||
| 6912 | 2155 | m_keyread_only = save_keyread_only; | |
| 6913 |
1/2✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
|
2155 | if (is_new_snapshot) { |
| 6914 |
1/2✓ Branch 0 taken 2155 times.
✗ Branch 1 not taken.
|
2155 | tx->release_snapshot(); |
| 6915 | } | ||
| 6916 | |||
| 6917 | 2155 | active_index = save_active_index; | |
| 6918 | |||
| 6919 | /* | ||
| 6920 | Do what ha_rocksdb::index_end() does. | ||
| 6921 | (Why don't we use index_init/index_end? class handler defines index_init | ||
| 6922 | as private, for some reason). | ||
| 6923 | */ | ||
| 6924 | 2155 | std::swap(m_iterator, save_iterator); | |
| 6925 | |||
| 6926 | 2155 | return last_val; | |
| 6927 | 2155 | } | |
| 6928 | |||
| 6929 | 8190165 | void ha_rocksdb::update_auto_incr_val(ulonglong val) { | |
| 6930 | 8190165 | ulonglong auto_incr_val = m_tbl_def->m_auto_incr_val; | |
| 6931 | 8150539 | while ( | |
| 6932 |
3/4✓ Branch 0 taken 1515625 times.
✓ Branch 1 taken 6633248 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8150539 times.
|
9666164 | auto_incr_val < val && |
| 6933 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1515625 times.
|
3031250 | !m_tbl_def->m_auto_incr_val.compare_exchange_weak(auto_incr_val, val)) { |
| 6934 | // Do nothing - just loop until auto_incr_val is >= val or we successfully | ||
| 6935 | // set it | ||
| 6936 | } | ||
| 6937 | 8150539 | } | |
| 6938 | |||
| 6939 | 8155900 | void ha_rocksdb::update_auto_incr_val_from_field() { | |
| 6940 | Field *field; | ||
| 6941 | ulonglong new_val, max_val; | ||
| 6942 | 8155900 | field = table->key_info[table->s->next_number_index].key_part[0].field; | |
| 6943 | 8155900 | max_val = rdb_get_int_col_max_value(field); | |
| 6944 | |||
| 6945 | my_bitmap_map *const old_map = | ||
| 6946 | 8179923 | dbug_tmp_use_all_columns(table, table->read_set); | |
| 6947 | 8166542 | new_val = field->val_int(); | |
| 6948 | // don't increment if we would wrap around | ||
| 6949 |
1/2✓ Branch 0 taken 8183373 times.
✗ Branch 1 not taken.
|
8182315 | if (new_val != max_val) { |
| 6950 | 8183373 | new_val++; | |
| 6951 | } | ||
| 6952 | |||
| 6953 | 8182315 | dbug_tmp_restore_column_map(table->read_set, old_map); | |
| 6954 | |||
| 6955 | // Only update if positive value was set for auto_incr column. | ||
| 6956 |
1/2✓ Branch 0 taken 8183657 times.
✗ Branch 1 not taken.
|
8182156 | if (new_val <= max_val) { |
| 6957 | 8183657 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); | |
| 6958 |
1/2✓ Branch 0 taken 8252588 times.
✗ Branch 1 not taken.
|
8163975 | tx->set_auto_incr(m_tbl_def->get_autoincr_gl_index_id(), new_val); |
| 6959 | |||
| 6960 | // Update the in memory auto_incr value in m_tbl_def. | ||
| 6961 | 8252588 | update_auto_incr_val(new_val); | |
| 6962 | } | ||
| 6963 | 8148934 | } | |
| 6964 | |||
| 6965 | 84 | int ha_rocksdb::load_hidden_pk_value() { | |
| 6966 | 84 | const int save_active_index = active_index; | |
| 6967 | 84 | active_index = MAX_KEY; | |
| 6968 | |||
| 6969 | std::unique_ptr<Rdb_iterator> save_iterator(new Rdb_iterator_base( | ||
| 6970 |
4/8✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✗ Branch 7 not taken.
|
168 | ha_thd(), m_key_descr_arr[active_index_pos()], m_pk_descr, m_tbl_def)); |
| 6971 | 84 | std::swap(m_iterator, save_iterator); | |
| 6972 | |||
| 6973 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); |
| 6974 | 84 | const bool is_new_snapshot = !tx->has_snapshot(); | |
| 6975 | |||
| 6976 | 84 | longlong hidden_pk_id = 1; | |
| 6977 | 84 | longlong old = 0; | |
| 6978 | 84 | int rc = 0; | |
| 6979 | // Do a lookup. | ||
| 6980 |
3/4✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 21 times.
|
84 | if (!index_last(table->record[0])) { |
| 6981 | /* | ||
| 6982 | Decode PK field from the key | ||
| 6983 | */ | ||
| 6984 |
1/2✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
|
63 | rc = read_hidden_pk_id_from_rowkey(&hidden_pk_id); |
| 6985 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
|
63 | if (rc) { |
| 6986 | ✗ | goto exit; | |
| 6987 | } | ||
| 6988 | |||
| 6989 | 63 | hidden_pk_id++; | |
| 6990 | } | ||
| 6991 | |||
| 6992 | 84 | old = m_tbl_def->m_hidden_pk_val; | |
| 6993 |
2/4✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
|
168 | while (old < hidden_pk_id && |
| 6994 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
168 | !m_tbl_def->m_hidden_pk_val.compare_exchange_weak(old, hidden_pk_id)) { |
| 6995 | } | ||
| 6996 | |||
| 6997 | 84 | exit: | |
| 6998 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | if (is_new_snapshot) { |
| 6999 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | tx->release_snapshot(); |
| 7000 | } | ||
| 7001 | |||
| 7002 | 84 | active_index = save_active_index; | |
| 7003 | 84 | std::swap(m_iterator, save_iterator); | |
| 7004 | |||
| 7005 | 84 | return rc; | |
| 7006 | 84 | } | |
| 7007 | |||
| 7008 | /* Get PK value from m_tbl_def->m_hidden_pk_info. */ | ||
| 7009 | 400949 | longlong ha_rocksdb::update_hidden_pk_val() { | |
| 7010 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 400949 times.
|
400949 | assert(has_hidden_pk(table)); |
| 7011 | 400949 | const longlong new_val = m_tbl_def->m_hidden_pk_val++; | |
| 7012 | 400949 | return new_val; | |
| 7013 | } | ||
| 7014 | |||
| 7015 | /* Get the id of the hidden pk id from m_last_rowkey */ | ||
| 7016 | 109298 | int ha_rocksdb::read_hidden_pk_id_from_rowkey(longlong *const hidden_pk_id) { | |
| 7017 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109298 times.
|
109298 | assert(hidden_pk_id != nullptr); |
| 7018 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109298 times.
|
109298 | assert(table != nullptr); |
| 7019 |
2/4✓ Branch 0 taken 109298 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 109298 times.
|
109298 | assert(has_hidden_pk(table)); |
| 7020 | |||
| 7021 | 109298 | rocksdb::Slice rowkey_slice(m_last_rowkey.ptr(), m_last_rowkey.length()); | |
| 7022 | |||
| 7023 | // Get hidden primary key from old key slice | ||
| 7024 | 109298 | Rdb_string_reader reader(&rowkey_slice); | |
| 7025 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109298 times.
|
109298 | if ((!reader.read(Rdb_key_def::INDEX_NUMBER_SIZE))) { |
| 7026 | ✗ | return HA_ERR_ROCKSDB_CORRUPT_DATA; | |
| 7027 | } | ||
| 7028 | |||
| 7029 | 109298 | const int length = Field_longlong::PACK_LENGTH; | |
| 7030 | 109298 | const uchar *from = reinterpret_cast<const uchar *>(reader.read(length)); | |
| 7031 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109298 times.
|
109298 | if (from == nullptr) { |
| 7032 | /* Mem-comparable image doesn't have enough bytes */ | ||
| 7033 | ✗ | return HA_ERR_ROCKSDB_CORRUPT_DATA; | |
| 7034 | } | ||
| 7035 | |||
| 7036 | 109298 | *hidden_pk_id = rdb_netbuf_read_uint64(&from); | |
| 7037 | 109298 | return HA_EXIT_SUCCESS; | |
| 7038 | } | ||
| 7039 | |||
| 7040 | /** | ||
| 7041 | @brief | ||
| 7042 | Free lock controls. We call this whenever we close a table. If the table had | ||
| 7043 | the last reference to the table_handler, then we free the memory associated | ||
| 7044 | with it. | ||
| 7045 | */ | ||
| 7046 | |||
| 7047 | 24020 | void Rdb_open_tables_map::release_table_handler( | |
| 7048 | Rdb_table_handler *const table_handler) { | ||
| 7049 | 24020 | RDB_MUTEX_LOCK_CHECK(m_mutex); | |
| 7050 | |||
| 7051 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24022 times.
|
24022 | assert(table_handler != nullptr); |
| 7052 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24022 times.
|
24022 | assert(table_handler->m_ref_count > 0); |
| 7053 |
2/2✓ Branch 0 taken 17879 times.
✓ Branch 1 taken 6143 times.
|
24022 | if (!--table_handler->m_ref_count) { |
| 7054 | const auto ret MY_ATTRIBUTE((__unused__)) = | ||
| 7055 |
2/4✓ Branch 0 taken 17879 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17879 times.
✗ Branch 3 not taken.
|
17879 | m_table_map.erase(std::string(table_handler->m_table_name)); |
| 7056 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17879 times.
|
17879 | assert(ret == 1); // the hash entry must actually be found and deleted |
| 7057 | 17879 | my_core::thr_lock_delete(&table_handler->m_thr_lock); | |
| 7058 | 17879 | my_free(table_handler); | |
| 7059 | } | ||
| 7060 | |||
| 7061 | 24022 | RDB_MUTEX_UNLOCK_CHECK(m_mutex); | |
| 7062 | 24022 | } | |
| 7063 | |||
| 7064 | 109518 | static handler *rocksdb_create_handler(my_core::handlerton *const hton, | |
| 7065 | my_core::TABLE_SHARE *const table_arg, | ||
| 7066 | bool partitioned, | ||
| 7067 | my_core::MEM_ROOT *const mem_root) { | ||
| 7068 |
2/2✓ Branch 0 taken 10783 times.
✓ Branch 1 taken 98735 times.
|
109518 | if (partitioned) { |
| 7069 |
2/4✓ Branch 0 taken 10783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10783 times.
✗ Branch 3 not taken.
|
10783 | ha_rockspart *file = new (mem_root) ha_rockspart(hton, table_arg); |
| 7070 |
3/6✓ Branch 0 taken 10783 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10783 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10783 times.
|
10783 | if (file && file->init_partitioning(mem_root)) { |
| 7071 | ✗ | destroy(file); | |
| 7072 | ✗ | return (nullptr); | |
| 7073 | } | ||
| 7074 | 10783 | return (file); | |
| 7075 | } | ||
| 7076 | |||
| 7077 |
2/4✓ Branch 0 taken 98735 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98735 times.
✗ Branch 3 not taken.
|
98735 | return new (mem_root) ha_rocksdb(hton, table_arg); |
| 7078 | } | ||
| 7079 | |||
| 7080 | 131969 | ha_rocksdb::ha_rocksdb(my_core::handlerton *const hton, | |
| 7081 | 131969 | my_core::TABLE_SHARE *const table_arg) | |
| 7082 | : handler(hton, table_arg), | ||
| 7083 | 131972 | m_table_handler(nullptr), | |
| 7084 | 131972 | m_tbl_def(nullptr), | |
| 7085 | 131972 | m_pk_descr(nullptr), | |
| 7086 | 131972 | m_key_descr_arr(nullptr), | |
| 7087 | 131972 | m_pk_can_be_decoded(true), | |
| 7088 | 131972 | m_pk_packed_tuple(nullptr), | |
| 7089 | 131972 | m_sk_packed_tuple(nullptr), | |
| 7090 | 131972 | m_end_key_packed_tuple(nullptr), | |
| 7091 | 131973 | m_sk_packed_tuple_old(nullptr), | |
| 7092 | 131973 | m_pack_buffer(nullptr), | |
| 7093 | 131971 | m_lock_rows(RDB_LOCK_NONE), | |
| 7094 | 131971 | m_keyread_only(false), | |
| 7095 | 131971 | m_iteration_only(false), | |
| 7096 | 131971 | m_insert_with_update(false), | |
| 7097 | 131971 | m_dup_key_found(false), | |
| 7098 | #if defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 7099 | 131972 | m_in_rpl_delete_rows(false), | |
| 7100 | 131972 | m_in_rpl_update_rows(false), | |
| 7101 | #endif // defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 7102 |
3/6✓ Branch 0 taken 131971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 131971 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 131972 times.
✗ Branch 5 not taken.
|
263941 | m_need_build_decoder(false) { |
| 7103 | 131972 | } | |
| 7104 | |||
| 7105 | 263688 | ha_rocksdb::~ha_rocksdb() { | |
| 7106 | int err MY_ATTRIBUTE((__unused__)); | ||
| 7107 | 263688 | err = finalize_bulk_load(false); | |
| 7108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 131844 times.
|
263688 | if (err != 0) { |
| 7109 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 7110 | "Error %d finalizing bulk load while closing handler.", | ||
| 7111 | err); | ||
| 7112 | } | ||
| 7113 | } | ||
| 7114 | |||
| 7115 | 703 | const std::string &ha_rocksdb::get_table_basename() const { | |
| 7116 | 703 | return m_tbl_def->base_tablename(); | |
| 7117 | } | ||
| 7118 | |||
| 7119 | /** | ||
| 7120 | @return | ||
| 7121 | false OK | ||
| 7122 | other Error inpacking the data | ||
| 7123 | */ | ||
| 7124 | 30906 | bool ha_rocksdb::init_with_fields() { | |
| 7125 |
1/2✓ Branch 0 taken 30906 times.
✗ Branch 1 not taken.
|
30906 | DBUG_ENTER_FUNC(); |
| 7126 | |||
| 7127 | 30906 | const uint pk = table_share->primary_key; | |
| 7128 |
2/2✓ Branch 0 taken 16945 times.
✓ Branch 1 taken 13961 times.
|
30906 | if (pk != MAX_KEY) { |
| 7129 | 16945 | const uint key_parts = table_share->key_info[pk].user_defined_key_parts; | |
| 7130 |
1/2✓ Branch 0 taken 16945 times.
✗ Branch 1 not taken.
|
16945 | check_keyread_allowed(m_pk_can_be_decoded, table_share, pk /*PK*/, |
| 7131 | key_parts - 1, true); | ||
| 7132 | } else { | ||
| 7133 | 13961 | m_pk_can_be_decoded = false; | |
| 7134 | } | ||
| 7135 |
1/2✓ Branch 0 taken 30907 times.
✗ Branch 1 not taken.
|
30906 | cached_table_flags = table_flags(); |
| 7136 | |||
| 7137 |
1/2✓ Branch 0 taken 30907 times.
✗ Branch 1 not taken.
|
30907 | DBUG_RETURN(false); /* Ok */ |
| 7138 | } | ||
| 7139 | |||
| 7140 | 504 | bool ha_rocksdb::allow_unsafe_alter() noexcept { | |
| 7141 | 504 | return rocksdb_allow_unsafe_alter; | |
| 7142 | } | ||
| 7143 | |||
| 7144 | 351 | bool ha_rocksdb::rpl_can_handle_stm_event() const noexcept { | |
| 7145 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 347 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
351 | return !(rpl_skip_tx_api_var && !super_read_only); |
| 7146 | } | ||
| 7147 | |||
| 7148 | /* | ||
| 7149 | If the key is a TTL key, we may need to filter it out. | ||
| 7150 | |||
| 7151 | The purpose of read filtering for tables with TTL is to ensure that | ||
| 7152 | during a transaction a key which has expired already but not removed by | ||
| 7153 | compaction yet is not returned to the user. | ||
| 7154 | |||
| 7155 | Without this the user might be hit with problems such as disappearing | ||
| 7156 | rows within a transaction, etc, because the compaction filter ignores | ||
| 7157 | snapshots when filtering keys. | ||
| 7158 | */ | ||
| 7159 | 3987 | bool rdb_should_hide_ttl_rec(const Rdb_key_def &kd, | |
| 7160 | const rocksdb::Slice &ttl_rec_val, | ||
| 7161 | Rdb_transaction *tx) { | ||
| 7162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3987 times.
|
3987 | assert(kd.has_ttl()); |
| 7163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3987 times.
|
3987 | assert(kd.m_ttl_rec_offset != UINT_MAX); |
| 7164 | 3987 | THD *thd = tx->get_thd(); | |
| 7165 | 3987 | const int64_t curr_ts = tx->m_snapshot_timestamp; | |
| 7166 | |||
| 7167 | /* | ||
| 7168 | Curr_ts can only be 0 if there are no snapshots open. | ||
| 7169 | should_hide_ttl_rec can only be called when there is >=1 snapshots, unless | ||
| 7170 | we are filtering on the write path (single INSERT/UPDATE) in which case | ||
| 7171 | we are passed in the current time as curr_ts. | ||
| 7172 | |||
| 7173 | In the event curr_ts is 0, we always decide not to filter the record. We | ||
| 7174 | also log a warning and increment a diagnostic counter. | ||
| 7175 | */ | ||
| 7176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3987 times.
|
3987 | if (curr_ts == 0) { |
| 7177 | ✗ | assert(false); | |
| 7178 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 7179 | "TTL read filtering called with no snapshot."); | ||
| 7180 | rdb_update_global_stats(ROWS_UNFILTERED_NO_SNAPSHOT, 1); | ||
| 7181 | return false; | ||
| 7182 | } | ||
| 7183 | |||
| 7184 |
7/10✓ Branch 0 taken 3987 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1281 times.
✓ Branch 3 taken 2706 times.
✓ Branch 4 taken 1281 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1281 times.
✓ Branch 8 taken 2706 times.
✓ Branch 9 taken 1281 times.
|
3987 | if (!rdb_is_ttl_read_filtering_enabled() || !rdb_is_ttl_enabled()) { |
| 7185 | 2706 | return false; | |
| 7186 | } | ||
| 7187 | |||
| 7188 | 1281 | Rdb_string_reader reader(&ttl_rec_val); | |
| 7189 | |||
| 7190 | /* | ||
| 7191 | Find where the 8-byte ttl is for each record in this index. | ||
| 7192 | */ | ||
| 7193 | uint64 ts; | ||
| 7194 |
3/6✓ Branch 0 taken 1281 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1281 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1281 times.
|
1281 | if (!reader.read(kd.m_ttl_rec_offset) || reader.read_uint64(&ts)) { |
| 7195 | /* | ||
| 7196 | This condition should never be reached since all TTL records have an | ||
| 7197 | 8 byte ttl field in front. Don't filter the record out, and log an error. | ||
| 7198 | */ | ||
| 7199 | ✗ | std::string buf; | |
| 7200 | ✗ | buf = rdb_hexdump(ttl_rec_val.data(), ttl_rec_val.size(), | |
| 7201 | ✗ | RDB_MAX_HEXDUMP_LEN); | |
| 7202 | ✗ | const GL_INDEX_ID gl_index_id = kd.get_gl_index_id(); | |
| 7203 | ✗ | LogPluginErrMsg( | |
| 7204 | ERROR_LEVEL, 0, | ||
| 7205 | "Decoding ttl from PK value failed, for index (%u,%u), val: %s", | ||
| 7206 | gl_index_id.cf_id, gl_index_id.index_id, buf.c_str()); | ||
| 7207 | ✗ | assert(0); | |
| 7208 | return false; | ||
| 7209 | } | ||
| 7210 | |||
| 7211 | /* Hide record if it has expired before the current snapshot time. */ | ||
| 7212 | 1281 | uint64 read_filter_ts = 0; | |
| 7213 | #if !defined(NDEBUG) | ||
| 7214 |
1/2✓ Branch 0 taken 1281 times.
✗ Branch 1 not taken.
|
1281 | read_filter_ts += rdb_dbug_set_ttl_read_filter_ts(); |
| 7215 | #endif // !defined(NDEBUG) | ||
| 7216 | 1281 | bool is_hide_ttl = | |
| 7217 | 1281 | ts + kd.m_ttl_duration + read_filter_ts <= static_cast<uint64>(curr_ts); | |
| 7218 |
2/2✓ Branch 0 taken 831 times.
✓ Branch 1 taken 450 times.
|
1281 | if (is_hide_ttl) { |
| 7219 |
1/2✓ Branch 0 taken 831 times.
✗ Branch 1 not taken.
|
831 | rdb_update_global_stats(ROWS_FILTERED, 1); |
| 7220 | |||
| 7221 | /* increment examined row count when rows are skipped */ | ||
| 7222 |
1/2✓ Branch 0 taken 831 times.
✗ Branch 1 not taken.
|
831 | thd->inc_examined_row_count(1); |
| 7223 |
2/4✓ Branch 0 taken 831 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 831 times.
✗ Branch 3 not taken.
|
831 | DEBUG_SYNC(thd, "rocksdb.ttl_rows_examined"); |
| 7224 | } | ||
| 7225 | 1281 | return is_hide_ttl; | |
| 7226 | } | ||
| 7227 | |||
| 7228 | #ifndef NDEBUG | ||
| 7229 | ✗ | void dbug_append_garbage_at_end(rocksdb::PinnableSlice *on_disk_rec) { | |
| 7230 | ✗ | std::string str(on_disk_rec->data(), on_disk_rec->size()); | |
| 7231 | ✗ | on_disk_rec->Reset(); | |
| 7232 | ✗ | str.append("abc"); | |
| 7233 | ✗ | on_disk_rec->PinSelf(rocksdb::Slice(str)); | |
| 7234 | } | ||
| 7235 | |||
| 7236 | ✗ | void dbug_truncate_record(rocksdb::PinnableSlice *on_disk_rec) { | |
| 7237 | ✗ | on_disk_rec->remove_suffix(on_disk_rec->size()); | |
| 7238 | } | ||
| 7239 | |||
| 7240 | ✗ | void dbug_modify_rec_varchar12(rocksdb::PinnableSlice *on_disk_rec) { | |
| 7241 | ✗ | std::string res; | |
| 7242 | // The record is NULL-byte followed by VARCHAR(10). | ||
| 7243 | // Put the NULL-byte | ||
| 7244 | ✗ | res.append("\0", 1); | |
| 7245 | // Then, add a valid VARCHAR(12) value. | ||
| 7246 | ✗ | res.append("\xC", 1); | |
| 7247 | ✗ | res.append("123456789ab", 12); | |
| 7248 | |||
| 7249 | ✗ | on_disk_rec->Reset(); | |
| 7250 | ✗ | on_disk_rec->PinSelf(rocksdb::Slice(res)); | |
| 7251 | } | ||
| 7252 | |||
| 7253 | 1 | void dbug_create_err_inplace_alter() { | |
| 7254 | 1 | my_printf_error(ER_UNKNOWN_ERROR, | |
| 7255 | "Intentional failure in inplace alter occurred.", MYF(0)); | ||
| 7256 | 1 | } | |
| 7257 | #endif // !defined(NDEBUG) | ||
| 7258 | |||
| 7259 | 16319473 | int ha_rocksdb::convert_record_from_storage_format( | |
| 7260 | const rocksdb::Slice *const key, uchar *const buf) { | ||
| 7261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16319473 times.
|
16319473 | DBUG_EXECUTE_IF("myrocks_simulate_bad_row_read1", |
| 7262 | dbug_append_garbage_at_end(&m_retrieved_record);); | ||
| 7263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16319473 times.
|
16319473 | DBUG_EXECUTE_IF("myrocks_simulate_bad_row_read2", |
| 7264 | dbug_truncate_record(&m_retrieved_record);); | ||
| 7265 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16319473 times.
|
16319473 | DBUG_EXECUTE_IF("myrocks_simulate_bad_row_read3", |
| 7266 | dbug_modify_rec_varchar12(&m_retrieved_record);); | ||
| 7267 | |||
| 7268 | 16319473 | return convert_record_from_storage_format(key, &m_retrieved_record, buf); | |
| 7269 | } | ||
| 7270 | |||
| 7271 | /* | ||
| 7272 | @brief | ||
| 7273 | Unpack the record in this->m_retrieved_record and this->m_last_rowkey from | ||
| 7274 | storage format into buf (which can be table->record[0] or table->record[1]). | ||
| 7275 | |||
| 7276 | @param key Table record's key in mem-comparable form. | ||
| 7277 | @param buf Store record in table->record[0] format here | ||
| 7278 | |||
| 7279 | @detail | ||
| 7280 | If the table has blobs, the unpacked data in buf may keep pointers to the | ||
| 7281 | data in this->m_retrieved_record. | ||
| 7282 | |||
| 7283 | The key is only needed to check its checksum value (the checksum is in | ||
| 7284 | m_retrieved_record). | ||
| 7285 | |||
| 7286 | @seealso | ||
| 7287 | rdb_converter::setup_read_decoders() Sets up data structures which tell | ||
| 7288 | which columns to decode. | ||
| 7289 | |||
| 7290 | @return | ||
| 7291 | 0 OK | ||
| 7292 | other Error inpacking the data | ||
| 7293 | */ | ||
| 7294 | |||
| 7295 | 87773578 | int ha_rocksdb::convert_record_from_storage_format( | |
| 7296 | const rocksdb::Slice *const key, const rocksdb::Slice *const value, | ||
| 7297 | uchar *const buf) { | ||
| 7298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 87773578 times.
|
87773578 | assert(key != nullptr); |
| 7299 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 87773578 times.
|
87773578 | assert(buf != nullptr); |
| 7300 | |||
| 7301 | 87773578 | return m_converter->decode(m_pk_descr, buf, key, value); | |
| 7302 | } | ||
| 7303 | |||
| 7304 | 24478 | int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, | |
| 7305 | const Rdb_tbl_def *const tbl_def_arg) { | ||
| 7306 |
1/2✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
|
24478 | DBUG_ENTER_FUNC(); |
| 7307 | |||
| 7308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24478 times.
|
24478 | assert(tbl_def_arg != nullptr); |
| 7309 | |||
| 7310 | 24478 | std::shared_ptr<Rdb_key_def> *const kd_arr = tbl_def_arg->m_key_descr_arr; | |
| 7311 | |||
| 7312 | 24478 | uint max_packed_sk_len = 0; | |
| 7313 | 24478 | uint pack_key_len = 0; | |
| 7314 | |||
| 7315 |
1/2✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
|
24478 | m_pk_descr = kd_arr[pk_index(table_arg, tbl_def_arg)]; |
| 7316 | |||
| 7317 | // move this into get_table_handler() ?? | ||
| 7318 |
1/2✓ Branch 0 taken 24477 times.
✗ Branch 1 not taken.
|
24477 | m_pk_descr->setup(table_arg, tbl_def_arg); |
| 7319 | |||
| 7320 | 24477 | pack_key_len = m_pk_descr->max_storage_fmt_length(); | |
| 7321 | #ifdef HAVE_PSI_INTERFACE | ||
| 7322 | 24478 | m_pk_packed_tuple = static_cast<uchar *>( | |
| 7323 |
1/2✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
|
24478 | my_malloc(rdb_handler_memory_key, pack_key_len, MYF(0))); |
| 7324 | #else | ||
| 7325 | m_pk_packed_tuple = static_cast<uchar *>( | ||
| 7326 | my_malloc(PSI_NOT_INSTRUMENTED, pack_key_len, MYF(0))); | ||
| 7327 | #endif | ||
| 7328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24478 times.
|
24478 | if (m_pk_packed_tuple == nullptr) { |
| 7329 | ✗ | goto error; | |
| 7330 | } | ||
| 7331 | |||
| 7332 | /* Sometimes, we may use m_sk_packed_tuple for storing packed PK */ | ||
| 7333 | 24478 | max_packed_sk_len = pack_key_len; | |
| 7334 |
2/2✓ Branch 0 taken 34670 times.
✓ Branch 1 taken 24477 times.
|
59147 | for (uint i = 0; i < table_arg->s->keys; i++) { |
| 7335 | /* Primary key was processed above */ | ||
| 7336 |
2/2✓ Branch 0 taken 13670 times.
✓ Branch 1 taken 21000 times.
|
34670 | if (i == table_arg->s->primary_key) continue; |
| 7337 | |||
| 7338 | // TODO: move this into get_table_handler() ?? | ||
| 7339 |
1/2✓ Branch 0 taken 21000 times.
✗ Branch 1 not taken.
|
21000 | kd_arr[i]->setup(table_arg, tbl_def_arg); |
| 7340 | |||
| 7341 | 21000 | const uint packed_len = kd_arr[i]->max_storage_fmt_length(); | |
| 7342 |
2/2✓ Branch 0 taken 11578 times.
✓ Branch 1 taken 9421 times.
|
20999 | if (packed_len > max_packed_sk_len) { |
| 7343 | 11578 | max_packed_sk_len = packed_len; | |
| 7344 | } | ||
| 7345 | } | ||
| 7346 | |||
| 7347 | #ifdef HAVE_PSI_INTERFACE | ||
| 7348 | 48956 | if (!(m_sk_packed_tuple = static_cast<uchar *>( | |
| 7349 |
1/2✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
|
24477 | my_malloc(rdb_handler_memory_key, max_packed_sk_len, MYF(0)))) || |
| 7350 | 24478 | !(m_sk_packed_tuple_old = static_cast<uchar *>( | |
| 7351 |
2/4✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24478 times.
✗ Branch 3 not taken.
|
24478 | my_malloc(rdb_handler_memory_key, max_packed_sk_len, MYF(0)))) || |
| 7352 | 24477 | !(m_end_key_packed_tuple = static_cast<uchar *>( | |
| 7353 |
4/8✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24477 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 24478 times.
|
73434 | my_malloc(rdb_handler_memory_key, max_packed_sk_len, MYF(0)))) || |
| 7354 | 24478 | !(m_pack_buffer = static_cast<uchar *>( | |
| 7355 |
2/4✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24478 times.
|
24477 | my_malloc(rdb_handler_memory_key, max_packed_sk_len, MYF(0))))) { |
| 7356 | #else | ||
| 7357 | if (!(m_sk_packed_tuple = static_cast<uchar *>( | ||
| 7358 | my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)))) || | ||
| 7359 | !(m_sk_packed_tuple_old = static_cast<uchar *>( | ||
| 7360 | my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)))) || | ||
| 7361 | !(m_end_key_packed_tuple = static_cast<uchar *>( | ||
| 7362 | my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)))) || | ||
| 7363 | !(m_pack_buffer = static_cast<uchar *>( | ||
| 7364 | my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0))))) { | ||
| 7365 | #endif | ||
| 7366 | ✗ | goto error; | |
| 7367 | } | ||
| 7368 | |||
| 7369 |
1/2✓ Branch 0 taken 24478 times.
✗ Branch 1 not taken.
|
24478 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 7370 | |||
| 7371 | ✗ | error: | |
| 7372 | // If we're here then this means that at some point above an allocation may | ||
| 7373 | // have failed. To avoid any resource leaks and maintain a clear contract | ||
| 7374 | // we'll clean up before returning the error code. | ||
| 7375 | ✗ | free_key_buffers(); | |
| 7376 | |||
| 7377 | ✗ | DBUG_RETURN(HA_ERR_INTERNAL_ERROR); | |
| 7378 | } | ||
| 7379 | |||
| 7380 | 48483 | void ha_rocksdb::free_key_buffers() { | |
| 7381 | 48483 | my_free(m_pk_packed_tuple); | |
| 7382 | 48484 | m_pk_packed_tuple = nullptr; | |
| 7383 | |||
| 7384 | 48484 | my_free(m_sk_packed_tuple); | |
| 7385 | 48484 | m_sk_packed_tuple = nullptr; | |
| 7386 | |||
| 7387 | 48484 | my_free(m_sk_packed_tuple_old); | |
| 7388 | 48485 | m_sk_packed_tuple_old = nullptr; | |
| 7389 | |||
| 7390 | 48485 | my_free(m_end_key_packed_tuple); | |
| 7391 | 48485 | m_end_key_packed_tuple = nullptr; | |
| 7392 | |||
| 7393 | 48485 | my_free(m_pack_buffer); | |
| 7394 | 48485 | m_pack_buffer = nullptr; | |
| 7395 | |||
| 7396 | 48485 | release_blob_buffer(); | |
| 7397 | 48484 | } | |
| 7398 | |||
| 7399 | /** | ||
| 7400 | @return | ||
| 7401 | HA_EXIT_SUCCESS OK | ||
| 7402 | other HA_ERR error code (can be SE-specific) | ||
| 7403 | */ | ||
| 7404 | 24015 | int ha_rocksdb::open(const char *const name, int mode, uint test_if_locked, | |
| 7405 | const dd::Table *table_def MY_ATTRIBUTE((__unused__))) { | ||
| 7406 |
1/2✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
|
24015 | DBUG_ENTER_FUNC(); |
| 7407 | |||
| 7408 |
1/2✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
|
24016 | int err = close(); |
| 7409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24016 times.
|
24016 | if (err) { |
| 7410 | ✗ | DBUG_RETURN(err); | |
| 7411 | } | ||
| 7412 | |||
| 7413 |
1/2✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
|
24016 | m_table_handler = rdb_open_tables.get_table_handler(name); |
| 7414 | |||
| 7415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24016 times.
|
24016 | if (m_table_handler == nullptr) { |
| 7416 | ✗ | DBUG_RETURN(HA_ERR_OUT_OF_MEM); | |
| 7417 | } | ||
| 7418 | |||
| 7419 |
1/2✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
|
24016 | my_core::thr_lock_data_init(&m_table_handler->m_thr_lock, &m_db_lock, |
| 7420 | nullptr); | ||
| 7421 | 24016 | m_io_perf.init(&m_table_handler->m_table_perf_context, | |
| 7422 | 24016 | &m_table_handler->m_io_perf_read, &stats); | |
| 7423 | |||
| 7424 | Rdb_perf_context_guard guard(&m_io_perf, | ||
| 7425 |
3/6✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24016 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24016 times.
✗ Branch 5 not taken.
|
24016 | rocksdb_perf_context_level(ha_thd())); |
| 7426 | |||
| 7427 | 24016 | std::string fullname; | |
| 7428 |
2/4✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24016 times.
✗ Branch 3 not taken.
|
24016 | err = rdb_normalize_tablename(name, &fullname); |
| 7429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24016 times.
|
24016 | if (err != HA_EXIT_SUCCESS) { |
| 7430 | ✗ | rdb_open_tables.release_table_handler(m_table_handler); | |
| 7431 | ✗ | DBUG_RETURN(err); | |
| 7432 | } | ||
| 7433 | |||
| 7434 |
1/2✓ Branch 0 taken 24016 times.
✗ Branch 1 not taken.
|
24016 | m_tbl_def = ddl_manager.find(fullname); |
| 7435 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24010 times.
|
24016 | if (m_tbl_def == nullptr) { |
| 7436 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | rdb_open_tables.release_table_handler(m_table_handler); |
| 7437 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_INTERNAL_ERROR, MYF(0), |
| 7438 | "Attempt to open a table that is not present in RocksDB-SE data " | ||
| 7439 | "dictionary"); | ||
| 7440 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_ERR_ROCKSDB_INVALID_TABLE); |
| 7441 | } | ||
| 7442 | |||
| 7443 | 24010 | m_lock_rows = RDB_LOCK_NONE; | |
| 7444 | 24010 | m_locked_row_action = THR_WAIT; | |
| 7445 | 24010 | m_key_descr_arr = m_tbl_def->m_key_descr_arr; | |
| 7446 | |||
| 7447 | /* | ||
| 7448 | Full table scan actually uses primary key | ||
| 7449 | (UPDATE needs to know this, otherwise it will go into infinite loop on | ||
| 7450 | queries like "UPDATE tbl SET pk=pk+100") | ||
| 7451 | */ | ||
| 7452 | 24010 | key_used_on_scan = table->s->primary_key; | |
| 7453 | |||
| 7454 | // close() above has already called free_key_buffers(). No need to do it here. | ||
| 7455 |
1/2✓ Branch 0 taken 24010 times.
✗ Branch 1 not taken.
|
24010 | err = alloc_key_buffers(table, m_tbl_def); |
| 7456 | |||
| 7457 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24010 times.
|
24010 | if (err) { |
| 7458 | ✗ | rdb_open_tables.release_table_handler(m_table_handler); | |
| 7459 | ✗ | DBUG_RETURN(err); | |
| 7460 | } | ||
| 7461 | |||
| 7462 | /* | ||
| 7463 | init_with_fields() is used to initialize table flags based on the field | ||
| 7464 | definitions in table->field[]. | ||
| 7465 | It is called by open_binary_frm(), but that function calls the method for | ||
| 7466 | a temporary ha_rocksdb object which is later destroyed. | ||
| 7467 | |||
| 7468 | If we are here in ::open(), then init_with_fields() has not been called | ||
| 7469 | for this object. Call it ourselves, we want all member variables to be | ||
| 7470 | properly initialized. | ||
| 7471 | */ | ||
| 7472 |
1/2✓ Branch 0 taken 24010 times.
✗ Branch 1 not taken.
|
24010 | init_with_fields(); |
| 7473 | |||
| 7474 | /* Initialize decoder */ | ||
| 7475 |
3/6✓ Branch 0 taken 24010 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24010 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24008 times.
✗ Branch 5 not taken.
|
24010 | m_converter.reset(new Rdb_converter(ha_thd(), m_tbl_def, table)); |
| 7476 | |||
| 7477 | /* | ||
| 7478 | Update m_ttl_bytes address to same as Rdb_converter's m_ttl_bytes. | ||
| 7479 | Remove this code after moving convert_record_to_storage_format() into | ||
| 7480 | Rdb_converter class. | ||
| 7481 | */ | ||
| 7482 | 24007 | m_ttl_bytes = m_converter->get_ttl_bytes_buffer(); | |
| 7483 | |||
| 7484 |
1/2✓ Branch 0 taken 24009 times.
✗ Branch 1 not taken.
|
24005 | info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); |
| 7485 | |||
| 7486 | /* | ||
| 7487 | The following load_XXX code calls row decode functions, and they do | ||
| 7488 | that without having done ::external_lock() or index_init()/rnd_init(). | ||
| 7489 | (Note: this also means we're doing a read when there was no | ||
| 7490 | rdb_converter::setup_field_encoders() call) | ||
| 7491 | |||
| 7492 | Initialize the necessary variables for them: | ||
| 7493 | */ | ||
| 7494 | |||
| 7495 | /* Load auto_increment value only once on first use. */ | ||
| 7496 |
6/6✓ Branch 0 taken 4642 times.
✓ Branch 1 taken 19367 times.
✓ Branch 2 taken 2068 times.
✓ Branch 3 taken 2575 times.
✓ Branch 4 taken 2068 times.
✓ Branch 5 taken 21942 times.
|
24009 | if (table->found_next_number_field && m_tbl_def->m_auto_incr_val == 0) { |
| 7497 |
1/2✓ Branch 0 taken 2068 times.
✗ Branch 1 not taken.
|
2068 | load_auto_incr_value(); |
| 7498 | } | ||
| 7499 | |||
| 7500 | /* Load hidden pk only once on first use. */ | ||
| 7501 |
6/8✓ Branch 0 taken 24010 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10637 times.
✓ Branch 3 taken 13373 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 10553 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 24010 times.
|
24094 | if (has_hidden_pk(table) && m_tbl_def->m_hidden_pk_val == 0 && |
| 7502 |
2/4✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
|
84 | (err = load_hidden_pk_value()) != HA_EXIT_SUCCESS) { |
| 7503 | ✗ | rdb_open_tables.release_table_handler(m_table_handler); | |
| 7504 | ✗ | free_key_buffers(); | |
| 7505 | ✗ | DBUG_RETURN(err); | |
| 7506 | } | ||
| 7507 | |||
| 7508 | /* Index block size in MyRocks: used by MySQL in query optimization */ | ||
| 7509 | 24010 | stats.block_size = rocksdb_tbl_options->block_size; | |
| 7510 | |||
| 7511 |
1/2✓ Branch 0 taken 24010 times.
✗ Branch 1 not taken.
|
24010 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 7512 | 24016 | } | |
| 7513 | |||
| 7514 | 48000 | int ha_rocksdb::close(void) { | |
| 7515 |
1/2✓ Branch 0 taken 48002 times.
✗ Branch 1 not taken.
|
48000 | DBUG_ENTER_FUNC(); |
| 7516 | |||
| 7517 | 48002 | m_pk_descr = nullptr; | |
| 7518 | 48002 | m_key_descr_arr = nullptr; | |
| 7519 | 48002 | m_converter = nullptr; | |
| 7520 | 48002 | m_iterator = nullptr; | |
| 7521 |
1/2✓ Branch 0 taken 48001 times.
✗ Branch 1 not taken.
|
48002 | free_key_buffers(); |
| 7522 | |||
| 7523 |
2/2✓ Branch 0 taken 23961 times.
✓ Branch 1 taken 24040 times.
|
48001 | if (m_table_handler != nullptr) { |
| 7524 |
1/2✓ Branch 0 taken 23962 times.
✗ Branch 1 not taken.
|
23961 | rdb_open_tables.release_table_handler(m_table_handler); |
| 7525 | 23962 | m_table_handler = nullptr; | |
| 7526 | } | ||
| 7527 | |||
| 7528 | // These are needed to suppress valgrind errors in rocksdb.partition | ||
| 7529 |
1/2✓ Branch 0 taken 48001 times.
✗ Branch 1 not taken.
|
48002 | m_last_rowkey.mem_free(); |
| 7530 | 48001 | m_sk_tails.free(); | |
| 7531 | 48002 | m_sk_tails_old.free(); | |
| 7532 | 48002 | m_pk_unpack_info.free(); | |
| 7533 | |||
| 7534 |
1/2✓ Branch 0 taken 48002 times.
✗ Branch 1 not taken.
|
48002 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 7535 | } | ||
| 7536 | |||
| 7537 | static const char *rdb_error_messages[] = { | ||
| 7538 | "Table must have a PRIMARY KEY.", | ||
| 7539 | "Specifying DATA DIRECTORY for an individual table is not supported.", | ||
| 7540 | "Specifying INDEX DIRECTORY for an individual table is not supported.", | ||
| 7541 | "RocksDB commit failed.", | ||
| 7542 | "Failure during bulk load operation.", | ||
| 7543 | "Found data corruption.", | ||
| 7544 | "CRC checksum mismatch.", | ||
| 7545 | "Invalid table.", | ||
| 7546 | "Could not access RocksDB properties.", | ||
| 7547 | "File I/O error during merge/sort operation.", | ||
| 7548 | "RocksDB status: not found.", | ||
| 7549 | "RocksDB status: corruption.", | ||
| 7550 | "RocksDB status: not supported.", | ||
| 7551 | "RocksDB status: invalid argument.", | ||
| 7552 | "RocksDB status: io error.", | ||
| 7553 | "RocksDB status: no space.", | ||
| 7554 | "RocksDB status: merge in progress.", | ||
| 7555 | "RocksDB status: incomplete.", | ||
| 7556 | "RocksDB status: shutdown in progress.", | ||
| 7557 | "RocksDB status: timed out.", | ||
| 7558 | "RocksDB status: aborted.", | ||
| 7559 | "RocksDB status: lock limit reached.", | ||
| 7560 | "RocksDB status: busy.", | ||
| 7561 | "RocksDB status: deadlock.", | ||
| 7562 | "RocksDB status: expired.", | ||
| 7563 | "RocksDB status: try again.", | ||
| 7564 | }; | ||
| 7565 | |||
| 7566 | static_assert((sizeof(rdb_error_messages) / sizeof(rdb_error_messages[0])) == | ||
| 7567 | ((HA_ERR_ROCKSDB_LAST - HA_ERR_ROCKSDB_FIRST) + 1), | ||
| 7568 | "Number of error messages doesn't match number of error codes"); | ||
| 7569 | |||
| 7570 | 330 | static const char *rdb_get_error_messages(int error) { | |
| 7571 |
4/4✓ Branch 0 taken 83 times.
✓ Branch 1 taken 247 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 3 times.
|
330 | if (error >= HA_ERR_ROCKSDB_FIRST && error <= HA_ERR_ROCKSDB_LAST) { |
| 7572 | 80 | return rdb_error_messages[error - HA_ERR_ROCKSDB_FIRST]; | |
| 7573 | } | ||
| 7574 | 250 | return ""; | |
| 7575 | } | ||
| 7576 | |||
| 7577 | 330 | bool ha_rocksdb::get_error_message(const int error, String *const buf) { | |
| 7578 |
1/2✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
|
330 | DBUG_ENTER_FUNC(); |
| 7579 | |||
| 7580 | static_assert(HA_ERR_ROCKSDB_LAST > HA_ERR_FIRST, | ||
| 7581 | "HA_ERR_ROCKSDB_LAST > HA_ERR_FIRST"); | ||
| 7582 | static_assert(HA_ERR_ROCKSDB_LAST > HA_ERR_LAST, | ||
| 7583 | "HA_ERR_ROCKSDB_LAST > HA_ERR_LAST"); | ||
| 7584 | |||
| 7585 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
|
330 | assert(buf != nullptr); |
| 7586 | |||
| 7587 |
1/2✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
|
330 | buf->append(rdb_get_error_messages(error)); |
| 7588 | |||
| 7589 | // We can be called with the values which are < HA_ERR_FIRST because most | ||
| 7590 | // MySQL internal functions will just return HA_EXIT_FAILURE in case of | ||
| 7591 | // an error. | ||
| 7592 | |||
| 7593 |
1/2✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
|
330 | DBUG_RETURN(false); |
| 7594 | } | ||
| 7595 | |||
| 7596 | /* | ||
| 7597 | Generalized way to convert RocksDB status errors into MySQL error code, and | ||
| 7598 | print error message. | ||
| 7599 | |||
| 7600 | Each error code below maps to a RocksDB status code found in: | ||
| 7601 | rocksdb/include/rocksdb/status.h | ||
| 7602 | */ | ||
| 7603 | 24 | int ha_rocksdb::rdb_error_to_mysql(const rocksdb::Status &s, | |
| 7604 | const char *opt_msg) { | ||
| 7605 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
|
24 | assert(!s.ok()); |
| 7606 | |||
| 7607 | int err; | ||
| 7608 |
5/17✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 19 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
24 | switch (s.code()) { |
| 7609 | ✗ | case rocksdb::Status::Code::kOk: | |
| 7610 | ✗ | err = HA_EXIT_SUCCESS; | |
| 7611 | ✗ | break; | |
| 7612 | ✗ | case rocksdb::Status::Code::kNotFound: | |
| 7613 | ✗ | err = HA_ERR_ROCKSDB_STATUS_NOT_FOUND; | |
| 7614 | ✗ | break; | |
| 7615 | ✗ | case rocksdb::Status::Code::kCorruption: | |
| 7616 | ✗ | err = HA_ERR_ROCKSDB_STATUS_CORRUPTION; | |
| 7617 | ✗ | break; | |
| 7618 | ✗ | case rocksdb::Status::Code::kNotSupported: | |
| 7619 | ✗ | err = HA_ERR_ROCKSDB_STATUS_NOT_SUPPORTED; | |
| 7620 | ✗ | break; | |
| 7621 | ✗ | case rocksdb::Status::Code::kInvalidArgument: | |
| 7622 | ✗ | err = HA_ERR_ROCKSDB_STATUS_INVALID_ARGUMENT; | |
| 7623 | ✗ | break; | |
| 7624 | 1 | case rocksdb::Status::Code::kIOError: | |
| 7625 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | err = (s.IsNoSpace()) ? HA_ERR_ROCKSDB_STATUS_NO_SPACE |
| 7626 | : HA_ERR_ROCKSDB_STATUS_IO_ERROR; | ||
| 7627 | 1 | break; | |
| 7628 | ✗ | case rocksdb::Status::Code::kMergeInProgress: | |
| 7629 | ✗ | err = HA_ERR_ROCKSDB_STATUS_MERGE_IN_PROGRESS; | |
| 7630 | ✗ | break; | |
| 7631 | 3 | case rocksdb::Status::Code::kIncomplete: | |
| 7632 | 3 | err = HA_ERR_ROCKSDB_STATUS_INCOMPLETE; | |
| 7633 | 3 | break; | |
| 7634 | ✗ | case rocksdb::Status::Code::kShutdownInProgress: | |
| 7635 | ✗ | err = HA_ERR_ROCKSDB_STATUS_SHUTDOWN_IN_PROGRESS; | |
| 7636 | ✗ | break; | |
| 7637 | ✗ | case rocksdb::Status::Code::kTimedOut: | |
| 7638 | ✗ | err = HA_ERR_ROCKSDB_STATUS_TIMED_OUT; | |
| 7639 | ✗ | break; | |
| 7640 | 19 | case rocksdb::Status::Code::kAborted: | |
| 7641 |
3/4✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 2 times.
|
19 | err = (s.IsLockLimit()) ? HA_ERR_ROCKSDB_STATUS_LOCK_LIMIT |
| 7642 | : HA_ERR_ROCKSDB_STATUS_ABORTED; | ||
| 7643 | 19 | break; | |
| 7644 | 1 | case rocksdb::Status::Code::kBusy: | |
| 7645 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | err = (s.IsDeadlock()) ? HA_ERR_ROCKSDB_STATUS_DEADLOCK |
| 7646 | : HA_ERR_ROCKSDB_STATUS_BUSY; | ||
| 7647 | 1 | break; | |
| 7648 | ✗ | case rocksdb::Status::Code::kExpired: | |
| 7649 | ✗ | err = HA_ERR_ROCKSDB_STATUS_EXPIRED; | |
| 7650 | ✗ | break; | |
| 7651 | ✗ | case rocksdb::Status::Code::kTryAgain: | |
| 7652 | ✗ | err = HA_ERR_ROCKSDB_STATUS_TRY_AGAIN; | |
| 7653 | ✗ | break; | |
| 7654 | ✗ | default: | |
| 7655 | ✗ | assert(0); | |
| 7656 | return -1; | ||
| 7657 | } | ||
| 7658 | |||
| 7659 | 24 | std::string errMsg; | |
| 7660 |
3/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 7 times.
|
24 | if (s.IsLockLimit()) { |
| 7661 | errMsg = | ||
| 7662 | "Operation aborted: Failed to acquire lock due to " | ||
| 7663 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | "rocksdb_max_row_locks limit"; |
| 7664 | } else { | ||
| 7665 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | errMsg = s.ToString(); |
| 7666 | } | ||
| 7667 | |||
| 7668 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (opt_msg) { |
| 7669 | ✗ | std::string concatenated_error = errMsg + " (" + std::string(opt_msg) + ")"; | |
| 7670 | ✗ | my_error(ER_GET_ERRMSG, MYF(0), s.code(), concatenated_error.c_str(), | |
| 7671 | rocksdb_hton_name); | ||
| 7672 | ✗ | } else { | |
| 7673 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
24 | my_error(ER_GET_ERRMSG, MYF(0), s.code(), errMsg.c_str(), |
| 7674 | rocksdb_hton_name); | ||
| 7675 | } | ||
| 7676 | |||
| 7677 | 24 | return err; | |
| 7678 | } | ||
| 7679 | |||
| 7680 | /* | ||
| 7681 | Create structures needed for storing data in rocksdb. This is called when the | ||
| 7682 | table is created. The structures will be shared by all TABLE* objects. | ||
| 7683 | |||
| 7684 | @param | ||
| 7685 | table_arg Table with definition | ||
| 7686 | db_table "dbname.tablename" | ||
| 7687 | len strlen of the above | ||
| 7688 | actual_user_table_name actual table name in case of alter | ||
| 7689 | table copy algorithm | ||
| 7690 | tbl_def_arg tbl_def whose key_descr is being created/populated | ||
| 7691 | old_tbl_def_arg tbl_def from which keys are being copied over from | ||
| 7692 | (for use during inplace alter) | ||
| 7693 | |||
| 7694 | @return | ||
| 7695 | 0 - Ok | ||
| 7696 | other - error, either given table ddl is not supported by rocksdb or OOM. | ||
| 7697 | */ | ||
| 7698 | 15319 | int ha_rocksdb::create_key_defs( | |
| 7699 | const TABLE *const table_arg, Rdb_tbl_def *const tbl_def_arg, | ||
| 7700 | const std::string &actual_user_table_name, | ||
| 7701 | const TABLE *const old_table_arg /* = nullptr */, | ||
| 7702 | const Rdb_tbl_def *const old_tbl_def_arg | ||
| 7703 | /* = nullptr */) const { | ||
| 7704 |
1/2✓ Branch 0 taken 15319 times.
✗ Branch 1 not taken.
|
15319 | DBUG_ENTER_FUNC(); |
| 7705 | |||
| 7706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15319 times.
|
15319 | assert(table_arg != nullptr); |
| 7707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15319 times.
|
15319 | assert(table_arg->s != nullptr); |
| 7708 | |||
| 7709 |
5/8✓ Branch 0 taken 15319 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 15310 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
|
15319 | DBUG_EXECUTE_IF("rocksdb_truncate_failure", { |
| 7710 | my_error(ER_INTERNAL_ERROR, MYF(0), "Simulated truncation failure."); | ||
| 7711 | DBUG_RETURN(HA_EXIT_FAILURE); | ||
| 7712 | }); | ||
| 7713 | |||
| 7714 |
4/6✓ Branch 0 taken 15310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 15307 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
15310 | DBUG_EXECUTE_IF("rocksdb_truncate_failure_crash", DBUG_SUICIDE();); |
| 7715 | |||
| 7716 | /* | ||
| 7717 | These need to be one greater than MAX_INDEXES since the user can create | ||
| 7718 | MAX_INDEXES secondary keys and no primary key which would cause us | ||
| 7719 | to generate a hidden one. | ||
| 7720 | */ | ||
| 7721 | 15307 | std::array<key_def_cf_info, MAX_INDEXES + 1> cfs; | |
| 7722 | |||
| 7723 | /* | ||
| 7724 | NOTE: All new column families must be created before new index numbers are | ||
| 7725 | allocated to each key definition. See below for more details. | ||
| 7726 | http://github.com/MySQLOnRocksDB/mysql-5.6/issues/86#issuecomment-138515501 | ||
| 7727 | */ | ||
| 7728 |
3/4✓ Branch 0 taken 15307 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 15273 times.
|
15307 | if (create_cfs(table_arg, tbl_def_arg, actual_user_table_name, &cfs)) { |
| 7729 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7730 | } | ||
| 7731 | |||
| 7732 | 15273 | uint64 ttl_duration = 0; | |
| 7733 | 15273 | std::string ttl_column; | |
| 7734 | uint ttl_field_offset; | ||
| 7735 | |||
| 7736 | uint err; | ||
| 7737 |
3/4✓ Branch 0 taken 15273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 15249 times.
|
15273 | if ((err = Rdb_key_def::extract_ttl_duration(table_arg, tbl_def_arg, |
| 7738 | &ttl_duration))) { | ||
| 7739 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | DBUG_RETURN(err); |
| 7740 | } | ||
| 7741 | |||
| 7742 |
3/4✓ Branch 0 taken 15249 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 15153 times.
|
15249 | if ((err = Rdb_key_def::extract_ttl_col(table_arg, tbl_def_arg, &ttl_column, |
| 7743 | &ttl_field_offset))) { | ||
| 7744 |
1/2✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
|
96 | DBUG_RETURN(err); |
| 7745 | } | ||
| 7746 | |||
| 7747 | /* We don't currently support TTL on tables with hidden primary keys. */ | ||
| 7748 |
7/8✓ Branch 0 taken 963 times.
✓ Branch 1 taken 14190 times.
✓ Branch 2 taken 963 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 939 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 15129 times.
|
15153 | if (ttl_duration > 0 && has_hidden_pk(table_arg)) { |
| 7749 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | my_error(ER_RDB_TTL_UNSUPPORTED, MYF(0)); |
| 7750 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7751 | } | ||
| 7752 | |||
| 7753 | /* | ||
| 7754 | If TTL duration is not specified but TTL column was specified, throw an | ||
| 7755 | error because TTL column requires duration. | ||
| 7756 | */ | ||
| 7757 |
4/6✓ Branch 0 taken 14190 times.
✓ Branch 1 taken 939 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14190 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15129 times.
|
15129 | if (ttl_duration == 0 && !ttl_column.empty()) { |
| 7758 | ✗ | my_error(ER_RDB_TTL_COL_FORMAT, MYF(0), ttl_column.c_str()); | |
| 7759 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 7760 | } | ||
| 7761 | |||
| 7762 |
2/2✓ Branch 0 taken 14531 times.
✓ Branch 1 taken 598 times.
|
15129 | if (!old_tbl_def_arg) { |
| 7763 | /* | ||
| 7764 | old_tbl_def doesn't exist. this means we are in the process of creating | ||
| 7765 | a new table. | ||
| 7766 | |||
| 7767 | Get the index numbers (this will update the next_index_number) | ||
| 7768 | and create Rdb_key_def structures. | ||
| 7769 | */ | ||
| 7770 |
2/2✓ Branch 0 taken 26619 times.
✓ Branch 1 taken 14474 times.
|
41093 | for (uint i = 0; i < tbl_def_arg->m_key_count; i++) { |
| 7771 |
3/4✓ Branch 0 taken 26619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 26562 times.
|
26619 | if (create_key_def(table_arg, i, tbl_def_arg, &m_key_descr_arr[i], cfs[i], |
| 7772 | ttl_duration, ttl_column)) { | ||
| 7773 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7774 | } | ||
| 7775 | } | ||
| 7776 | } else { | ||
| 7777 | /* | ||
| 7778 | old_tbl_def exists. This means we are creating a new tbl_def as part of | ||
| 7779 | in-place alter table. Copy over existing keys from the old_tbl_def and | ||
| 7780 | generate the necessary new key definitions if any. | ||
| 7781 | */ | ||
| 7782 |
3/4✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 589 times.
|
598 | if (create_inplace_key_defs(table_arg, tbl_def_arg, old_table_arg, |
| 7783 | old_tbl_def_arg, cfs, ttl_duration, | ||
| 7784 | ttl_column)) { | ||
| 7785 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7786 | } | ||
| 7787 | } | ||
| 7788 | |||
| 7789 |
1/2✓ Branch 0 taken 15063 times.
✗ Branch 1 not taken.
|
15063 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 7790 | 15307 | } | |
| 7791 | |||
| 7792 | /* | ||
| 7793 | Checks index parameters and creates column families needed for storing data | ||
| 7794 | in rocksdb if necessary. | ||
| 7795 | |||
| 7796 | @param in | ||
| 7797 | table_arg Table with definition | ||
| 7798 | db_table Table name | ||
| 7799 | tbl_def_arg Table def structure being populated | ||
| 7800 | actual_user_table_name actual table name in case | ||
| 7801 | of alter table copy algorithm | ||
| 7802 | @param out | ||
| 7803 | cfs CF info for each key definition in 'key_info' order | ||
| 7804 | |||
| 7805 | @return | ||
| 7806 | 0 - Ok | ||
| 7807 | other - error | ||
| 7808 | */ | ||
| 7809 | 15307 | int ha_rocksdb::create_cfs( | |
| 7810 | const TABLE *const table_arg, Rdb_tbl_def *const tbl_def_arg, | ||
| 7811 | const std::string &actual_user_table_name, | ||
| 7812 | std::array<struct key_def_cf_info, MAX_INDEXES + 1> *const cfs) const { | ||
| 7813 |
1/2✓ Branch 0 taken 15307 times.
✗ Branch 1 not taken.
|
15307 | DBUG_ENTER_FUNC(); |
| 7814 | |||
| 7815 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15307 times.
|
15307 | assert(table_arg != nullptr); |
| 7816 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15307 times.
|
15307 | assert(table_arg->s != nullptr); |
| 7817 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15307 times.
|
15307 | assert(tbl_def_arg != nullptr); |
| 7818 | |||
| 7819 | char tablename_sys[NAME_LEN + 1]; | ||
| 7820 |
1/2✓ Branch 0 taken 15307 times.
✗ Branch 1 not taken.
|
15307 | my_core::filename_to_tablename(tbl_def_arg->base_tablename().c_str(), |
| 7821 | tablename_sys, sizeof(tablename_sys)); | ||
| 7822 | |||
| 7823 |
1/2✓ Branch 0 taken 15307 times.
✗ Branch 1 not taken.
|
15307 | uint primary_key_index = pk_index(table_arg, tbl_def_arg); |
| 7824 | std::string table_with_enforced_collation = | ||
| 7825 |
6/10✓ Branch 0 taken 13924 times.
✓ Branch 1 taken 1383 times.
✓ Branch 2 taken 13924 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1383 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13924 times.
✓ Branch 7 taken 1383 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
15307 | actual_user_table_name.empty() ? tablename_sys : actual_user_table_name; |
| 7826 | /* | ||
| 7827 | The first loop checks the index parameters and creates | ||
| 7828 | column families if necessary. | ||
| 7829 | */ | ||
| 7830 |
2/2✓ Branch 0 taken 28329 times.
✓ Branch 1 taken 15273 times.
|
43602 | for (uint i = 0; i < tbl_def_arg->m_key_count; i++) { |
| 7831 | 28329 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cf_handle; | |
| 7832 | |||
| 7833 | // Internal consistency check to make sure that data in TABLE and | ||
| 7834 | // Rdb_tbl_def structures matches. Either both are missing or both are | ||
| 7835 | // specified. Yes, this is critical enough to make it into SHIP_ASSERT. | ||
| 7836 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 28329 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
28329 | SHIP_ASSERT(!table_arg->part_info == tbl_def_arg->base_partition().empty()); |
| 7837 | |||
| 7838 | // Generate the name for the column family to use. | ||
| 7839 | 28329 | bool per_part_match_found = false; | |
| 7840 | std::string cf_name = | ||
| 7841 |
1/2✓ Branch 0 taken 28329 times.
✗ Branch 1 not taken.
|
28329 | generate_cf_name(i, table_arg, tbl_def_arg, &per_part_match_found); |
| 7842 | |||
| 7843 | // Prevent create from using the system column family. | ||
| 7844 |
6/6✓ Branch 0 taken 28320 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 28314 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 28314 times.
|
56649 | if (cf_name == DEFAULT_SYSTEM_CF_NAME || |
| 7845 | 28320 | cf_name == DEFAULT_TMP_SYSTEM_CF_NAME) { | |
| 7846 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | my_error(ER_WRONG_ARGUMENTS, MYF(0), |
| 7847 | "column family not valid for storing index data."); | ||
| 7848 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7849 | } | ||
| 7850 | |||
| 7851 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 28308 times.
|
28314 | if (cf_name == DEFAULT_TMP_CF_NAME) { |
| 7852 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_WRONG_ARGUMENTS, MYF(0), |
| 7853 | "reserved column family for storing temporary table data."); | ||
| 7854 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7855 | } | ||
| 7856 | // Populate cf_name for tmp tables. | ||
| 7857 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 28212 times.
|
28308 | if (is_tmp_table(tbl_def_arg->full_tablename())) { |
| 7858 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 93 times.
|
96 | if (!cf_name.empty()) { |
| 7859 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_WRONG_ARGUMENTS, MYF(0), |
| 7860 | "custom column family for temporary table is not allowed."); | ||
| 7861 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7862 | } | ||
| 7863 |
1/2✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
|
93 | cf_name = DEFAULT_TMP_CF_NAME; |
| 7864 | } | ||
| 7865 | |||
| 7866 |
7/12✓ Branch 0 taken 28305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 28302 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
|
28305 | DBUG_EXECUTE_IF("rocksdb_create_primary_cf", { |
| 7867 | if (cf_name == "cf_primary_key") { | ||
| 7868 | THD *const thd = my_core::thd_get_current_thd(); | ||
| 7869 | static constexpr char act[] = | ||
| 7870 | "now signal ready_to_mark_cf_dropped_in_create_cfs " | ||
| 7871 | "wait_for mark_cf_dropped_done_in_create_cfs"; | ||
| 7872 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 7873 | } | ||
| 7874 | }); | ||
| 7875 | |||
| 7876 |
8/12✓ Branch 0 taken 28305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 28299 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
|
28305 | DBUG_EXECUTE_IF("rocksdb_create_secondary_cf", { |
| 7877 | if (cf_name == "cf_secondary_key") { | ||
| 7878 | THD *const thd = my_core::thd_get_current_thd(); | ||
| 7879 | static constexpr char act[] = | ||
| 7880 | "now signal ready_to_mark_cf_dropped_in_create_cfs " | ||
| 7881 | "wait_for mark_cf_dropped_done_in_create_cfs"; | ||
| 7882 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 7883 | } | ||
| 7884 | }); | ||
| 7885 | |||
| 7886 | // if not specified, use default CF name | ||
| 7887 |
2/2✓ Branch 0 taken 26673 times.
✓ Branch 1 taken 1632 times.
|
28305 | if (cf_name.empty()) { |
| 7888 |
4/4✓ Branch 0 taken 12242 times.
✓ Branch 1 taken 14431 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 12233 times.
|
26673 | if (i != primary_key_index && rocksdb_use_default_sk_cf) |
| 7889 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | cf_name = DEFAULT_SK_CF_NAME; |
| 7890 | else | ||
| 7891 |
1/2✓ Branch 0 taken 26664 times.
✗ Branch 1 not taken.
|
26664 | cf_name = DEFAULT_CF_NAME; |
| 7892 | } | ||
| 7893 | |||
| 7894 | // Here's how `get_or_create_cf` will use the input parameters: | ||
| 7895 | // | ||
| 7896 | // `cf_name` - will be used as a CF name. | ||
| 7897 | { | ||
| 7898 | auto local_dict_manager = | ||
| 7899 |
1/2✓ Branch 0 taken 28305 times.
✗ Branch 1 not taken.
|
28305 | dict_manager.get_dict_manager_selector_non_const(cf_name); |
| 7900 |
1/2✓ Branch 0 taken 28305 times.
✗ Branch 1 not taken.
|
28305 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 7901 | 28305 | cf_handle = cf_manager.get_or_create_cf(rdb, cf_name, | |
| 7902 |
1/2✓ Branch 0 taken 28305 times.
✗ Branch 1 not taken.
|
28305 | !rocksdb_no_create_column_family); |
| 7903 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 28301 times.
|
28305 | if (!cf_handle) { |
| 7904 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7905 | } | ||
| 7906 | |||
| 7907 |
1/2✓ Branch 0 taken 28301 times.
✗ Branch 1 not taken.
|
28301 | uint32 cf_id = cf_handle->GetID(); |
| 7908 | |||
| 7909 | // If the cf is marked as dropped, we fail it here. | ||
| 7910 | // The cf can be dropped after this point, we will | ||
| 7911 | // check again when committing metadata changes. | ||
| 7912 |
3/4✓ Branch 0 taken 28301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 28295 times.
|
28301 | if (local_dict_manager->get_dropped_cf(cf_id)) { |
| 7913 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_CF_DROPPED, MYF(0), cf_name.c_str()); |
| 7914 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 7915 | } | ||
| 7916 | |||
| 7917 | 84885 | if (cf_manager.create_cf_flags_if_needed(local_dict_manager, | |
| 7918 |
3/6✓ Branch 0 taken 28295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28295 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28295 times.
|
28295 | cf_handle->GetID(), cf_name, |
| 7919 | per_part_match_found)) { | ||
| 7920 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 7921 | } | ||
| 7922 |
2/2✓ Branch 0 taken 28295 times.
✓ Branch 1 taken 10 times.
|
28305 | } |
| 7923 | |||
| 7924 | // The CF can be dropped from cf_manager at this point. This is part of | ||
| 7925 | // create table or alter table. If the drop happens before metadata are | ||
| 7926 | // written, create table or alter table will fail. | ||
| 7927 | 28295 | auto &cf = (*cfs)[i]; | |
| 7928 | |||
| 7929 | 28295 | cf.cf_handle = cf_handle; | |
| 7930 |
1/2✓ Branch 0 taken 28295 times.
✗ Branch 1 not taken.
|
28295 | cf.is_reverse_cf = Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str()); |
| 7931 | 28295 | cf.is_per_partition_cf = per_part_match_found; | |
| 7932 |
4/4✓ Branch 0 taken 28295 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 28295 times.
✓ Branch 3 taken 34 times.
|
28363 | } |
| 7933 | |||
| 7934 |
1/2✓ Branch 0 taken 15273 times.
✗ Branch 1 not taken.
|
15273 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 7935 | 15307 | } | |
| 7936 | |||
| 7937 | /* | ||
| 7938 | Create key definition needed for storing data in rocksdb during ADD index | ||
| 7939 | inplace operations. | ||
| 7940 | |||
| 7941 | @param in | ||
| 7942 | table_arg Table with definition | ||
| 7943 | tbl_def_arg New table def structure being populated | ||
| 7944 | old_tbl_def_arg Old(current) table def structure | ||
| 7945 | cfs Struct array which contains column family information | ||
| 7946 | |||
| 7947 | @return | ||
| 7948 | 0 - Ok | ||
| 7949 | other - error, either given table ddl is not supported by rocksdb or OOM. | ||
| 7950 | */ | ||
| 7951 | 598 | int ha_rocksdb::create_inplace_key_defs( | |
| 7952 | const TABLE *const table_arg, Rdb_tbl_def *const tbl_def_arg, | ||
| 7953 | const TABLE *const old_table_arg, const Rdb_tbl_def *const old_tbl_def_arg, | ||
| 7954 | const std::array<key_def_cf_info, MAX_INDEXES + 1> &cfs, | ||
| 7955 | uint64 ttl_duration, const std::string &ttl_column) const { | ||
| 7956 |
1/2✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
|
598 | DBUG_ENTER_FUNC(); |
| 7957 | |||
| 7958 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(table_arg != nullptr); |
| 7959 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(tbl_def_arg != nullptr); |
| 7960 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(old_tbl_def_arg != nullptr); |
| 7961 | |||
| 7962 | 598 | std::shared_ptr<Rdb_key_def> *const old_key_descr = | |
| 7963 | old_tbl_def_arg->m_key_descr_arr; | ||
| 7964 | 598 | std::shared_ptr<Rdb_key_def> *const new_key_descr = | |
| 7965 | tbl_def_arg->m_key_descr_arr; | ||
| 7966 | const std::unordered_map<std::string, uint> old_key_pos = | ||
| 7967 | get_old_key_positions(table_arg, tbl_def_arg, old_table_arg, | ||
| 7968 |
1/2✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
|
598 | old_tbl_def_arg); |
| 7969 | |||
| 7970 | uint i; | ||
| 7971 |
2/2✓ Branch 0 taken 1429 times.
✓ Branch 1 taken 589 times.
|
2018 | for (i = 0; i < tbl_def_arg->m_key_count; i++) { |
| 7972 |
3/6✓ Branch 0 taken 1429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1429 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1429 times.
✗ Branch 5 not taken.
|
1429 | const auto &it = old_key_pos.find(get_key_name(i, table_arg, tbl_def_arg)); |
| 7973 | |||
| 7974 |
2/2✓ Branch 0 taken 954 times.
✓ Branch 1 taken 475 times.
|
1429 | if (it != old_key_pos.end()) { |
| 7975 | /* | ||
| 7976 | Found matching index in old table definition, so copy it over to the | ||
| 7977 | new one created. | ||
| 7978 | */ | ||
| 7979 | 954 | const Rdb_key_def &okd = *old_key_descr[it->second]; | |
| 7980 | |||
| 7981 |
1/2✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
|
954 | const GL_INDEX_ID gl_index_id = okd.get_gl_index_id(); |
| 7982 | 954 | struct Rdb_index_info index_info; | |
| 7983 | 1908 | if (!dict_manager.get_dict_manager_selector_const(gl_index_id.cf_id) | |
| 7984 |
3/6✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 954 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 954 times.
|
954 | ->get_index_info(gl_index_id, &index_info)) { |
| 7985 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 7986 | "Could not get index information for Index Number " | ||
| 7987 | "(%u,%u), table %s", | ||
| 7988 | gl_index_id.cf_id, gl_index_id.index_id, | ||
| 7989 | old_tbl_def_arg->full_tablename().c_str()); | ||
| 7990 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 7991 | } | ||
| 7992 | |||
| 7993 | uint32 ttl_rec_offset = | ||
| 7994 |
1/2✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
|
954 | Rdb_key_def::has_index_flag(index_info.m_index_flags, |
| 7995 | Rdb_key_def::TTL_FLAG) | ||
| 7996 |
3/4✓ Branch 0 taken 39 times.
✓ Branch 1 taken 915 times.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
|
954 | ? Rdb_key_def::calculate_index_flag_offset( |
| 7997 | index_info.m_index_flags, Rdb_key_def::TTL_FLAG) | ||
| 7998 | 954 | : UINT_MAX; | |
| 7999 | |||
| 8000 | /* | ||
| 8001 | We can't use the copy constructor because we need to update the | ||
| 8002 | keynr within the pack_info for each field and the keyno of the keydef | ||
| 8003 | itself. | ||
| 8004 | */ | ||
| 8005 | 954 | new_key_descr[i] = std::make_shared<Rdb_key_def>( | |
| 8006 |
1/2✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
|
1908 | okd.get_index_number(), i, okd.get_shared_cf(), |
| 8007 | index_info.m_index_dict_version, index_info.m_index_type, | ||
| 8008 | 954 | index_info.m_kv_version, okd.m_is_reverse_cf, | |
| 8009 | 954 | okd.m_is_per_partition_cf, okd.m_name.c_str(), | |
| 8010 | 954 | dict_manager.get_dict_manager_selector_const(gl_index_id.cf_id) | |
| 8011 |
2/4✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 954 times.
✗ Branch 3 not taken.
|
1908 | ->get_stats(gl_index_id), |
| 8012 | 954 | index_info.m_index_flags, ttl_rec_offset, index_info.m_ttl_duration); | |
| 8013 |
3/4✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 466 times.
|
475 | } else if (create_key_def(table_arg, i, tbl_def_arg, &new_key_descr[i], |
| 8014 | 475 | cfs[i], ttl_duration, ttl_column)) { | |
| 8015 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 8016 | } | ||
| 8017 | |||
| 8018 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1420 times.
|
1420 | assert(new_key_descr[i] != nullptr); |
| 8019 |
1/2✓ Branch 0 taken 1420 times.
✗ Branch 1 not taken.
|
1420 | new_key_descr[i]->setup(table_arg, tbl_def_arg); |
| 8020 | } | ||
| 8021 | |||
| 8022 | 589 | tbl_def_arg->m_tbl_stats.set(new_key_descr[0]->m_stats.m_rows, 0, 0); | |
| 8023 | |||
| 8024 |
1/2✓ Branch 0 taken 589 times.
✗ Branch 1 not taken.
|
589 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 8025 | 598 | } | |
| 8026 | |||
| 8027 | 598 | std::unordered_map<std::string, uint> ha_rocksdb::get_old_key_positions( | |
| 8028 | const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg, | ||
| 8029 | const TABLE *const old_table_arg, | ||
| 8030 | const Rdb_tbl_def *const old_tbl_def_arg) const { | ||
| 8031 |
1/2✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
|
598 | DBUG_ENTER_FUNC(); |
| 8032 | |||
| 8033 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(table_arg != nullptr); |
| 8034 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(old_table_arg != nullptr); |
| 8035 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(tbl_def_arg != nullptr); |
| 8036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598 times.
|
598 | assert(old_tbl_def_arg != nullptr); |
| 8037 | |||
| 8038 | 598 | std::shared_ptr<Rdb_key_def> *const old_key_descr = | |
| 8039 | old_tbl_def_arg->m_key_descr_arr; | ||
| 8040 | 598 | std::unordered_map<std::string, uint> old_key_pos; | |
| 8041 | 598 | std::unordered_map<std::string, uint> new_key_pos; | |
| 8042 | uint i; | ||
| 8043 | |||
| 8044 |
2/2✓ Branch 0 taken 1429 times.
✓ Branch 1 taken 598 times.
|
2027 | for (i = 0; i < tbl_def_arg->m_key_count; i++) { |
| 8045 |
3/6✓ Branch 0 taken 1429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1429 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1429 times.
✗ Branch 5 not taken.
|
1429 | new_key_pos[get_key_name(i, table_arg, tbl_def_arg)] = i; |
| 8046 | } | ||
| 8047 | |||
| 8048 |
2/2✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 598 times.
|
1734 | for (i = 0; i < old_tbl_def_arg->m_key_count; i++) { |
| 8049 |
3/4✓ Branch 0 taken 1136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 944 times.
|
1136 | if (is_hidden_pk(i, old_table_arg, old_tbl_def_arg)) { |
| 8050 |
1/2✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
|
192 | old_key_pos[old_key_descr[i]->m_name] = i; |
| 8051 | 374 | continue; | |
| 8052 | } | ||
| 8053 | |||
| 8054 | /* | ||
| 8055 | In case of matching key name, need to check key parts of keys as well, | ||
| 8056 | in case a simultaneous drop + add is performed, where the key name is the | ||
| 8057 | same but the key parts are different. | ||
| 8058 | |||
| 8059 | Example: | ||
| 8060 | CREATE TABLE t1 (a INT, b INT, KEY ka(a)) ENGINE=RocksDB; | ||
| 8061 | ALTER TABLE t1 DROP INDEX ka, ADD INDEX ka(b), ALGORITHM=INPLACE; | ||
| 8062 | */ | ||
| 8063 | 944 | const KEY *const old_key = &old_table_arg->key_info[i]; | |
| 8064 |
2/4✓ Branch 0 taken 944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 944 times.
✗ Branch 3 not taken.
|
944 | const auto &it = new_key_pos.find(old_key->name); |
| 8065 |
2/2✓ Branch 0 taken 170 times.
✓ Branch 1 taken 774 times.
|
944 | if (it == new_key_pos.end()) { |
| 8066 | 170 | continue; | |
| 8067 | } | ||
| 8068 | |||
| 8069 | 774 | KEY *const new_key = &table_arg->key_info[it->second]; | |
| 8070 | |||
| 8071 | /* | ||
| 8072 | Check that the key is identical between old and new tables. | ||
| 8073 | If not, we still need to create a new index. | ||
| 8074 | |||
| 8075 | The exception is if there is an index changed from unique to non-unique, | ||
| 8076 | in these cases we don't need to rebuild as they are stored the same way in | ||
| 8077 | RocksDB. | ||
| 8078 | */ | ||
| 8079 | 774 | bool unique_to_non_unique = | |
| 8080 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 768 times.
|
780 | ((old_key->flags ^ new_key->flags) == HA_NOSAME) && |
| 8081 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | (old_key->flags & HA_NOSAME); |
| 8082 | |||
| 8083 |
6/8✓ Branch 0 taken 774 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 768 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 768 times.
|
774 | if (compare_keys(old_key, new_key) && !unique_to_non_unique) { |
| 8084 | 6 | continue; | |
| 8085 | } | ||
| 8086 | |||
| 8087 | /* Check to make sure key parts match. */ | ||
| 8088 |
3/4✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 762 times.
|
768 | if (compare_key_parts(old_key, new_key)) { |
| 8089 | 6 | continue; | |
| 8090 | } | ||
| 8091 | |||
| 8092 |
2/4✓ Branch 0 taken 762 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 762 times.
✗ Branch 3 not taken.
|
762 | old_key_pos[old_key->name] = i; |
| 8093 | } | ||
| 8094 | |||
| 8095 |
1/2✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
|
1196 | DBUG_RETURN(old_key_pos); |
| 8096 | 598 | } | |
| 8097 | |||
| 8098 | /* Check to see if two keys are identical. */ | ||
| 8099 | 2145 | int ha_rocksdb::compare_keys(const KEY *const old_key, | |
| 8100 | const KEY *const new_key) const { | ||
| 8101 |
1/2✓ Branch 0 taken 2145 times.
✗ Branch 1 not taken.
|
2145 | DBUG_ENTER_FUNC(); |
| 8102 | |||
| 8103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2145 times.
|
2145 | assert(old_key != nullptr); |
| 8104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2145 times.
|
2145 | assert(new_key != nullptr); |
| 8105 | |||
| 8106 | /* Check index name. */ | ||
| 8107 |
2/2✓ Branch 0 taken 723 times.
✓ Branch 1 taken 1422 times.
|
2145 | if (strcmp(old_key->name, new_key->name) != 0) { |
| 8108 |
1/2✓ Branch 0 taken 723 times.
✗ Branch 1 not taken.
|
723 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 8109 | } | ||
| 8110 | |||
| 8111 | /* If index algorithms are different then keys are different. */ | ||
| 8112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1422 times.
|
1422 | if (old_key->algorithm != new_key->algorithm) { |
| 8113 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 8114 | } | ||
| 8115 | |||
| 8116 | /* Check that the key is identical between old and new tables. */ | ||
| 8117 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1416 times.
|
1422 | if ((old_key->flags ^ new_key->flags) & HA_KEYFLAG_MASK) { |
| 8118 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 8119 | } | ||
| 8120 | |||
| 8121 | /* Check index comment. (for column family changes) */ | ||
| 8122 |
1/2✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
|
1416 | std::string old_comment(old_key->comment.str, old_key->comment.length); |
| 8123 |
1/2✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
|
1416 | std::string new_comment(new_key->comment.str, new_key->comment.length); |
| 8124 |
2/4✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1416 times.
|
1416 | if (old_comment.compare(new_comment) != 0) { |
| 8125 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 8126 | } | ||
| 8127 | |||
| 8128 |
1/2✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
|
1416 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 8129 | 1416 | } | |
| 8130 | |||
| 8131 | /* Check two keys to ensure that key parts within keys match */ | ||
| 8132 | 768 | int ha_rocksdb::compare_key_parts(const KEY *const old_key, | |
| 8133 | const KEY *const new_key) const { | ||
| 8134 |
1/2✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
|
768 | DBUG_ENTER_FUNC(); |
| 8135 | |||
| 8136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
|
768 | assert(old_key != nullptr); |
| 8137 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
|
768 | assert(new_key != nullptr); |
| 8138 | |||
| 8139 | /* Skip if key parts do not match, as it is a different key */ | ||
| 8140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
|
768 | if (new_key->user_defined_key_parts != old_key->user_defined_key_parts) { |
| 8141 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 8142 | } | ||
| 8143 | |||
| 8144 | /* Check to see that key parts themselves match */ | ||
| 8145 |
2/2✓ Branch 0 taken 1117 times.
✓ Branch 1 taken 762 times.
|
1879 | for (uint i = 0; i < old_key->user_defined_key_parts; i++) { |
| 8146 | 1117 | if (strcmp(old_key->key_part[i].field->field_name, | |
| 8147 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1114 times.
|
1117 | new_key->key_part[i].field->field_name) != 0) { |
| 8148 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 8149 | } | ||
| 8150 | |||
| 8151 | /* Check if prefix index key part length has changed */ | ||
| 8152 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1111 times.
|
1114 | if (old_key->key_part[i].length != new_key->key_part[i].length) { |
| 8153 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 8154 | } | ||
| 8155 | } | ||
| 8156 | |||
| 8157 |
1/2✓ Branch 0 taken 762 times.
✗ Branch 1 not taken.
|
762 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 8158 | } | ||
| 8159 | |||
| 8160 | /* | ||
| 8161 | Create key definition needed for storing data in rocksdb. | ||
| 8162 | This can be called either during CREATE table or doing ADD index operations. | ||
| 8163 | |||
| 8164 | @param in | ||
| 8165 | table_arg Table with definition | ||
| 8166 | i Position of index being created inside table_arg->key_info | ||
| 8167 | tbl_def_arg Table def structure being populated | ||
| 8168 | cf_info Struct which contains column family information | ||
| 8169 | |||
| 8170 | @param out | ||
| 8171 | new_key_def Newly created index definition. | ||
| 8172 | |||
| 8173 | @return | ||
| 8174 | 0 - Ok | ||
| 8175 | other - error, either given table ddl is not supported by rocksdb or OOM. | ||
| 8176 | */ | ||
| 8177 | 27094 | int ha_rocksdb::create_key_def(const TABLE *const table_arg, const uint i, | |
| 8178 | const Rdb_tbl_def *const tbl_def_arg, | ||
| 8179 | std::shared_ptr<Rdb_key_def> *const new_key_def, | ||
| 8180 | const struct key_def_cf_info &cf_info, | ||
| 8181 | uint64 ttl_duration, | ||
| 8182 | const std::string &ttl_column) const { | ||
| 8183 |
1/2✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
|
27094 | DBUG_ENTER_FUNC(); |
| 8184 | |||
| 8185 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27094 times.
|
27094 | assert(new_key_def != nullptr); |
| 8186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27094 times.
|
27094 | assert(*new_key_def == nullptr); |
| 8187 | |||
| 8188 | const uint index_id = | ||
| 8189 |
2/4✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27094 times.
✗ Branch 3 not taken.
|
27094 | ddl_manager.get_and_update_next_number(cf_info.cf_handle->GetID()); |
| 8190 | 27094 | const uint16_t index_dict_version = Rdb_key_def::INDEX_INFO_VERSION_LATEST; | |
| 8191 | uchar index_type; | ||
| 8192 | uint16_t kv_version; | ||
| 8193 | |||
| 8194 |
3/4✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5920 times.
✓ Branch 3 taken 21174 times.
|
27094 | if (is_hidden_pk(i, table_arg, tbl_def_arg)) { |
| 8195 | 5920 | index_type = Rdb_key_def::INDEX_TYPE_HIDDEN_PRIMARY; | |
| 8196 | 5920 | kv_version = Rdb_key_def::PRIMARY_FORMAT_VERSION_LATEST; | |
| 8197 |
2/2✓ Branch 0 taken 8605 times.
✓ Branch 1 taken 12569 times.
|
21174 | } else if (i == table_arg->s->primary_key) { |
| 8198 | 8605 | index_type = Rdb_key_def::INDEX_TYPE_PRIMARY; | |
| 8199 | 8605 | uint16 pk_latest_version = Rdb_key_def::PRIMARY_FORMAT_VERSION_LATEST; | |
| 8200 | 8605 | kv_version = pk_latest_version; | |
| 8201 | } else { | ||
| 8202 | 12569 | index_type = Rdb_key_def::INDEX_TYPE_SECONDARY; | |
| 8203 | 12569 | uint16 sk_latest_version = Rdb_key_def::SECONDARY_FORMAT_VERSION_LATEST; | |
| 8204 | 12569 | kv_version = sk_latest_version; | |
| 8205 | } | ||
| 8206 | |||
| 8207 | // Use PRIMARY_FORMAT_VERSION_UPDATE1 here since it is the same value as | ||
| 8208 | // SECONDARY_FORMAT_VERSION_UPDATE1 so it doesn't matter if this is a | ||
| 8209 | // primary key or secondary key. | ||
| 8210 |
3/4✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 27088 times.
|
27094 | DBUG_EXECUTE_IF("MYROCKS_LEGACY_VARBINARY_FORMAT", { |
| 8211 | kv_version = Rdb_key_def::PRIMARY_FORMAT_VERSION_UPDATE1; | ||
| 8212 | }); | ||
| 8213 | |||
| 8214 |
2/6✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27094 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
27094 | DBUG_EXECUTE_IF("MYROCKS_NO_COVERED_BITMAP_FORMAT", { |
| 8215 | if (index_type == Rdb_key_def::INDEX_TYPE_SECONDARY) { | ||
| 8216 | kv_version = Rdb_key_def::SECONDARY_FORMAT_VERSION_UPDATE2; | ||
| 8217 | } | ||
| 8218 | }); | ||
| 8219 | |||
| 8220 |
5/6✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 27079 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 12 times.
|
27094 | DBUG_EXECUTE_IF("MYROCKS_NO_LEAD_BYTE_VARCHAR_SPACE_PADDED", { |
| 8221 | if (index_type == Rdb_key_def::INDEX_TYPE_SECONDARY) { | ||
| 8222 | kv_version = Rdb_key_def::SECONDARY_FORMAT_VERSION_TTL; | ||
| 8223 | } else { | ||
| 8224 | kv_version = Rdb_key_def::PRIMARY_FORMAT_VERSION_TTL; | ||
| 8225 | } | ||
| 8226 | }); | ||
| 8227 | |||
| 8228 |
2/2✓ Branch 0 taken 1317 times.
✓ Branch 1 taken 25777 times.
|
27094 | uint32 index_flags = (ttl_duration > 0 ? Rdb_key_def::TTL_FLAG : 0); |
| 8229 | |||
| 8230 | uint32 ttl_rec_offset = | ||
| 8231 |
1/2✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
|
27094 | Rdb_key_def::has_index_flag(index_flags, Rdb_key_def::TTL_FLAG) |
| 8232 |
3/4✓ Branch 0 taken 1317 times.
✓ Branch 1 taken 25777 times.
✓ Branch 2 taken 1317 times.
✗ Branch 3 not taken.
|
27094 | ? Rdb_key_def::calculate_index_flag_offset(index_flags, |
| 8233 | Rdb_key_def::TTL_FLAG) | ||
| 8234 | 27094 | : UINT_MAX; | |
| 8235 | |||
| 8236 |
1/2✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
|
27094 | const char *const key_name = get_key_name(i, table_arg, m_tbl_def); |
| 8237 | 27094 | *new_key_def = std::make_shared<Rdb_key_def>( | |
| 8238 | 27094 | index_id, i, cf_info.cf_handle, index_dict_version, index_type, | |
| 8239 |
1/2✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
|
27094 | kv_version, cf_info.is_reverse_cf, cf_info.is_per_partition_cf, key_name, |
| 8240 |
1/2✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
|
81282 | Rdb_index_stats(), index_flags, ttl_rec_offset, ttl_duration); |
| 8241 | |||
| 8242 |
2/2✓ Branch 0 taken 588 times.
✓ Branch 1 taken 26506 times.
|
27094 | if (!ttl_column.empty()) { |
| 8243 |
1/2✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
|
588 | (*new_key_def)->m_ttl_column = ttl_column; |
| 8244 | } | ||
| 8245 | |||
| 8246 |
3/4✓ Branch 0 taken 27094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 27028 times.
|
27094 | if ((*new_key_def)->extract_partial_index_info(table_arg, tbl_def_arg)) { |
| 8247 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 8248 | } | ||
| 8249 | |||
| 8250 | // initialize key_def | ||
| 8251 |
1/2✓ Branch 0 taken 27028 times.
✗ Branch 1 not taken.
|
27028 | (*new_key_def)->setup(table_arg, tbl_def_arg); |
| 8252 |
1/2✓ Branch 0 taken 27028 times.
✗ Branch 1 not taken.
|
27028 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 8253 | } | ||
| 8254 | |||
| 8255 | 10256 | bool rdb_is_tablename_normalized(const std::string &tablename) { | |
| 8256 |
4/6✓ Branch 0 taken 10256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✓ Branch 3 taken 5238 times.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
|
10256 | return tablename.size() < 2 || (tablename[0] != '.' && tablename[1] != '/'); |
| 8257 | } | ||
| 8258 | |||
| 8259 | 56809 | int rdb_normalize_tablename(const std::string &tablename, | |
| 8260 | std::string *const strbuf) { | ||
| 8261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56809 times.
|
56809 | assert(strbuf != nullptr); |
| 8262 | |||
| 8263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56809 times.
|
56809 | if (tablename.size() < 2) { |
| 8264 | ✗ | assert(0); // We were not passed table name? | |
| 8265 | return HA_ERR_ROCKSDB_INVALID_TABLE; | ||
| 8266 | } | ||
| 8267 | |||
| 8268 | 56809 | size_t pos = tablename.find_last_of('/'); | |
| 8269 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56810 times.
|
56810 | if (pos == std::string::npos) { |
| 8270 | ✗ | assert(0); // We were not passed table name? | |
| 8271 | return HA_ERR_ROCKSDB_INVALID_TABLE; | ||
| 8272 | } | ||
| 8273 | |||
| 8274 |
1/2✓ Branch 0 taken 56810 times.
✗ Branch 1 not taken.
|
56810 | std::string table_name = tablename.substr(pos + 1); |
| 8275 | 56810 | std::string schema_name; | |
| 8276 | /* | ||
| 8277 | Special parsing for tmp tables. | ||
| 8278 | We will return TMP_SCHEMA_NAME for external/internal tmp tables by | ||
| 8279 | parsing the values passed to tablename from sql layer. | ||
| 8280 | |||
| 8281 | Below are different tablename for various cases: | ||
| 8282 | 1) Create user table : tablename = "./<SCHEMA>/<TABLE>" | ||
| 8283 | 2) Alter user table : tablename = "./<SCHEMA>/#sql_*" | ||
| 8284 | 3) External tmp tables : tablename = "/<TMP_DIRECTORY_PATH>/#sql_*" | ||
| 8285 | 4) Intrinsic tmp tables: tablename = "/<TMP_DIRECTORY_PATH>/#sql_*" | ||
| 8286 | */ | ||
| 8287 |
4/4✓ Branch 0 taken 254 times.
✓ Branch 1 taken 56555 times.
✓ Branch 2 taken 245 times.
✓ Branch 3 taken 56565 times.
|
57065 | if (strlen(opt_mysql_tmpdir) < tablename.length() && |
| 8288 |
2/2✓ Branch 0 taken 246 times.
✓ Branch 1 taken 9 times.
|
254 | strncmp(opt_mysql_tmpdir, tablename.c_str(), strlen(opt_mysql_tmpdir)) == |
| 8289 | 0) { | ||
| 8290 |
1/2✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
|
245 | schema_name = TMP_SCHEMA_NAME; |
| 8291 | } else { | ||
| 8292 |
3/6✓ Branch 0 taken 56564 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56564 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 56564 times.
|
56565 | if (tablename[0] != '.' || tablename[1] != '/') { |
| 8293 | ✗ | assert(0); | |
| 8294 | return HA_ERR_ROCKSDB_INVALID_TABLE; | ||
| 8295 | } | ||
| 8296 |
1/2✓ Branch 0 taken 56564 times.
✗ Branch 1 not taken.
|
56564 | schema_name = tablename.substr(2, pos - 2); |
| 8297 | } | ||
| 8298 |
2/4✓ Branch 0 taken 56809 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56809 times.
✗ Branch 3 not taken.
|
56809 | *strbuf = schema_name + "." + table_name; |
| 8299 | |||
| 8300 | 56810 | return HA_EXIT_SUCCESS; | |
| 8301 | 56810 | } | |
| 8302 | |||
| 8303 | /* | ||
| 8304 | Check to see if the user's original statement includes foreign key | ||
| 8305 | references | ||
| 8306 | */ | ||
| 8307 | 14460 | bool ha_rocksdb::contains_foreign_key(THD *const thd) { | |
| 8308 | bool success; | ||
| 8309 |
1/2✓ Branch 0 taken 14460 times.
✗ Branch 1 not taken.
|
14460 | const char *str = thd->query().str; |
| 8310 | |||
| 8311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14460 times.
|
14460 | assert(str != nullptr); |
| 8312 | |||
| 8313 |
1/2✓ Branch 0 taken 14472 times.
✗ Branch 1 not taken.
|
14472 | while (*str != '\0') { |
| 8314 | // Scan from our current pos looking for 'FOREIGN' | ||
| 8315 |
1/2✓ Branch 0 taken 14472 times.
✗ Branch 1 not taken.
|
14472 | str = rdb_find_in_string(str, "FOREIGN", &success); |
| 8316 |
2/2✓ Branch 0 taken 14442 times.
✓ Branch 1 taken 30 times.
|
14472 | if (!success) { |
| 8317 | 14442 | return false; | |
| 8318 | } | ||
| 8319 | |||
| 8320 | // Skip past the found "FOREIGN' | ||
| 8321 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | str = rdb_check_next_token(&my_charset_bin, str, "FOREIGN", &success); |
| 8322 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | assert(success); |
| 8323 | |||
| 8324 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
|
30 | if (!my_isspace(&my_charset_bin, *str)) { |
| 8325 | 6 | return false; | |
| 8326 | } | ||
| 8327 | |||
| 8328 | // See if the next token is 'KEY' | ||
| 8329 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | str = rdb_check_next_token(&my_charset_bin, str, "KEY", &success); |
| 8330 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
|
24 | if (!success) { |
| 8331 | 12 | continue; | |
| 8332 | } | ||
| 8333 | |||
| 8334 | // See if the next token is '(' | ||
| 8335 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | str = rdb_check_next_token(&my_charset_bin, str, "(", &success); |
| 8336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!success) { |
| 8337 | // There is an optional index id after 'FOREIGN KEY', skip it | ||
| 8338 | ✗ | str = rdb_skip_id(&my_charset_bin, str); | |
| 8339 | |||
| 8340 | // Now check for '(' again | ||
| 8341 | ✗ | str = rdb_check_next_token(&my_charset_bin, str, "(", &success); | |
| 8342 | } | ||
| 8343 | |||
| 8344 | // If we have found 'FOREIGN KEY [<word>] (' we can be confident we have | ||
| 8345 | // a foreign key clause. | ||
| 8346 | 12 | return success; | |
| 8347 | } | ||
| 8348 | |||
| 8349 | // We never found a valid foreign key clause | ||
| 8350 | ✗ | return false; | |
| 8351 | } | ||
| 8352 | |||
| 8353 | /** | ||
| 8354 | @brief | ||
| 8355 | splits the normalized table name of <dbname>.<tablename>#P#<part_no> into | ||
| 8356 | the <dbname>, <tablename> and <part_no> components. | ||
| 8357 | |||
| 8358 | @param dbbuf returns database name/table_schema | ||
| 8359 | @param tablebuf returns tablename | ||
| 8360 | @param partitionbuf returns partition suffix if there is one | ||
| 8361 | @return HA_EXIT_SUCCESS on success, non-zero on failure to split | ||
| 8362 | */ | ||
| 8363 | 34204 | int rdb_split_normalized_tablename(const std::string &fullname, | |
| 8364 | std::string *const db, | ||
| 8365 | std::string *const table, | ||
| 8366 | std::string *const partition) { | ||
| 8367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34204 times.
|
34204 | assert(!fullname.empty()); |
| 8368 | |||
| 8369 | #define RDB_PARTITION_STR "#P#" | ||
| 8370 | |||
| 8371 | /* Normalize returns dbname.tablename. */ | ||
| 8372 | 34204 | size_t dotpos = fullname.find('.'); | |
| 8373 | |||
| 8374 | /* Invalid table name? */ | ||
| 8375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34204 times.
|
34204 | if (dotpos == std::string::npos) { |
| 8376 | ✗ | return HA_ERR_ROCKSDB_INVALID_TABLE; | |
| 8377 | } | ||
| 8378 | |||
| 8379 | // Table must have a database name associated with it. | ||
| 8380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34204 times.
|
34204 | assert(dotpos > 0); |
| 8381 | |||
| 8382 |
1/2✓ Branch 0 taken 34204 times.
✗ Branch 1 not taken.
|
34204 | if (db != nullptr) { |
| 8383 | 34204 | *db = fullname.substr(0, dotpos); | |
| 8384 | } | ||
| 8385 | |||
| 8386 | 34204 | dotpos++; | |
| 8387 | |||
| 8388 | const size_t partpos = | ||
| 8389 | 34204 | fullname.find(RDB_PARTITION_STR, dotpos, strlen(RDB_PARTITION_STR)); | |
| 8390 | |||
| 8391 |
2/2✓ Branch 0 taken 13891 times.
✓ Branch 1 taken 20313 times.
|
34204 | if (partpos != std::string::npos) { |
| 8392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13891 times.
|
13891 | assert(partpos >= dotpos); |
| 8393 | |||
| 8394 |
2/2✓ Branch 0 taken 8691 times.
✓ Branch 1 taken 5200 times.
|
13891 | if (table != nullptr) { |
| 8395 | 8691 | *table = fullname.substr(dotpos, partpos - dotpos); | |
| 8396 | } | ||
| 8397 | |||
| 8398 |
2/2✓ Branch 0 taken 8691 times.
✓ Branch 1 taken 5200 times.
|
13891 | if (partition != nullptr) { |
| 8399 | 8691 | *partition = fullname.substr(partpos + strlen(RDB_PARTITION_STR)); | |
| 8400 | } | ||
| 8401 |
2/2✓ Branch 0 taken 15257 times.
✓ Branch 1 taken 5056 times.
|
20313 | } else if (table != nullptr) { |
| 8402 | 15257 | *table = fullname.substr(dotpos); | |
| 8403 | } | ||
| 8404 | |||
| 8405 | 34204 | return HA_EXIT_SUCCESS; | |
| 8406 | } | ||
| 8407 | |||
| 8408 | /* | ||
| 8409 | Generates the normalized tablename using as many of the given arguments as | ||
| 8410 | possible. Any of the three arguments to <db>.<table>#P#<partition> can be | ||
| 8411 | null/empty, but return string will only ever be of the form | ||
| 8412 | <db> | ||
| 8413 | <db>.<table> | ||
| 8414 | <db>.<table>#P#<partition> | ||
| 8415 | <table> | ||
| 8416 | <table>#P#<partition> | ||
| 8417 | */ | ||
| 8418 | 2500 | void rdb_gen_normalized_tablename(const std::string *db, | |
| 8419 | const std::string *table, | ||
| 8420 | const std::string *partition, | ||
| 8421 | std::string *fullname) { | ||
| 8422 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2500 times.
|
2500 | if (!fullname) return; |
| 8423 | 2500 | fullname->clear(); | |
| 8424 |
3/6✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2500 times.
✗ Branch 5 not taken.
|
2500 | if (db && db->length() > 0) *fullname += *db; |
| 8425 | |||
| 8426 | /* If table was not passed in, the partition will be ignored too */ | ||
| 8427 |
3/6✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2500 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2500 times.
|
2500 | if (!table || table->length() == 0) return; |
| 8428 | |||
| 8429 |
1/2✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
|
2500 | if (fullname->length() > 0) *fullname += "."; |
| 8430 | 2500 | *fullname += *table; | |
| 8431 | |||
| 8432 |
5/6✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1553 times.
✓ Branch 3 taken 947 times.
✓ Branch 4 taken 1553 times.
✓ Branch 5 taken 947 times.
|
2500 | if (partition && partition->length() > 0) { |
| 8433 |
3/6✓ Branch 0 taken 1553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1553 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1553 times.
✗ Branch 5 not taken.
|
1553 | *fullname += std::string(RDB_PARTITION_STR) + *partition; |
| 8434 | } | ||
| 8435 | } | ||
| 8436 | |||
| 8437 | /* | ||
| 8438 | Create a table's Rdb_tbl_def and its Rdb_key_defs and store table information | ||
| 8439 | into MyRocks Data Dictionary | ||
| 8440 | The method is called during create table/partition, truncate table/partition | ||
| 8441 | |||
| 8442 | @param table_name IN table's name formated as | ||
| 8443 | 'dbname.tablename' | ||
| 8444 | @param actual_user_table_name IN actual table name in case | ||
| 8445 | of alter table copy algorithm | ||
| 8446 | @param table_arg IN sql table | ||
| 8447 | @param auto_increment_value IN specified table's auto increment value | ||
| 8448 | |||
| 8449 | @return | ||
| 8450 | HA_EXIT_SUCCESS OK | ||
| 8451 | other HA_ERR error code (can be SE-specific) | ||
| 8452 | */ | ||
| 8453 | 14718 | int ha_rocksdb::create_table(const std::string &table_name, | |
| 8454 | const std::string &actual_user_table_name, | ||
| 8455 | const TABLE *table_arg, | ||
| 8456 | ulonglong auto_increment_value, | ||
| 8457 | dd::Table *table_def MY_ATTRIBUTE((__unused__))) { | ||
| 8458 |
1/2✓ Branch 0 taken 14718 times.
✗ Branch 1 not taken.
|
14718 | DBUG_ENTER_FUNC(); |
| 8459 | |||
| 8460 | int err; | ||
| 8461 |
1/2✓ Branch 0 taken 14718 times.
✗ Branch 1 not taken.
|
14718 | auto local_dict_manager = dict_manager.get_dict_manager_selector_non_const( |
| 8462 | 14718 | is_tmp_table(table_name)); | |
| 8463 |
1/2✓ Branch 0 taken 14718 times.
✗ Branch 1 not taken.
|
14718 | const std::unique_ptr<rocksdb::WriteBatch> wb = local_dict_manager->begin(); |
| 8464 | 14718 | rocksdb::WriteBatch *const batch = wb.get(); | |
| 8465 | |||
| 8466 | /* Create table/key descriptions and put them into the data dictionary */ | ||
| 8467 |
2/4✓ Branch 0 taken 14718 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14718 times.
✗ Branch 3 not taken.
|
14718 | m_tbl_def = new Rdb_tbl_def(table_name); |
| 8468 | |||
| 8469 | 14718 | uint n_keys = table_arg->s->keys; | |
| 8470 | |||
| 8471 | /* | ||
| 8472 | If no primary key found, create a hidden PK and place it inside table | ||
| 8473 | definition | ||
| 8474 | */ | ||
| 8475 |
3/4✓ Branch 0 taken 14718 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5956 times.
✓ Branch 3 taken 8762 times.
|
14718 | if (has_hidden_pk(table_arg)) { |
| 8476 | 5956 | n_keys += 1; | |
| 8477 | // reset hidden pk id | ||
| 8478 | // the starting valid value for hidden pk is 1 | ||
| 8479 | 5956 | m_tbl_def->m_hidden_pk_val = 1; | |
| 8480 | } | ||
| 8481 | |||
| 8482 |
4/6✓ Branch 0 taken 14718 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14718 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26906 times.
✓ Branch 5 taken 14718 times.
|
41624 | m_key_descr_arr = new std::shared_ptr<Rdb_key_def>[n_keys]; |
| 8483 | 14718 | m_tbl_def->m_key_count = n_keys; | |
| 8484 | 14718 | m_tbl_def->m_pk_index = table_arg->s->primary_key; | |
| 8485 | 14718 | m_tbl_def->m_key_descr_arr = m_key_descr_arr; | |
| 8486 | |||
| 8487 |
1/2✓ Branch 0 taken 14715 times.
✗ Branch 1 not taken.
|
14718 | err = create_key_defs(table_arg, m_tbl_def, actual_user_table_name); |
| 8488 |
2/2✓ Branch 0 taken 241 times.
✓ Branch 1 taken 14474 times.
|
14715 | if (err != HA_EXIT_SUCCESS) { |
| 8489 | 241 | goto error; | |
| 8490 | } | ||
| 8491 | |||
| 8492 |
1/2✓ Branch 0 taken 14474 times.
✗ Branch 1 not taken.
|
14474 | m_pk_descr = m_key_descr_arr[pk_index(table_arg, m_tbl_def)]; |
| 8493 | |||
| 8494 |
2/2✓ Branch 0 taken 509 times.
✓ Branch 1 taken 13965 times.
|
14474 | if (auto_increment_value) { |
| 8495 | 509 | bool autoinc_upgrade_test = false; | |
| 8496 | 509 | m_tbl_def->m_auto_incr_val = auto_increment_value; | |
| 8497 |
2/4✓ Branch 0 taken 509 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 509 times.
|
509 | DBUG_EXECUTE_IF("myrocks_autoinc_upgrade", autoinc_upgrade_test = true;); |
| 8498 |
1/2✓ Branch 0 taken 509 times.
✗ Branch 1 not taken.
|
509 | if (!autoinc_upgrade_test) { |
| 8499 | auto s = local_dict_manager->put_auto_incr_val( | ||
| 8500 | 509 | batch, m_tbl_def->get_autoincr_gl_index_id(), | |
| 8501 |
2/4✓ Branch 0 taken 509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 509 times.
✗ Branch 3 not taken.
|
509 | m_tbl_def->m_auto_incr_val); |
| 8502 |
2/4✓ Branch 0 taken 509 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 509 times.
|
509 | if (!s.ok()) { |
| 8503 | ✗ | goto error; | |
| 8504 | } | ||
| 8505 |
1/2✓ Branch 0 taken 509 times.
✗ Branch 1 not taken.
|
509 | } |
| 8506 | } | ||
| 8507 | |||
| 8508 |
6/10✓ Branch 0 taken 14474 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 14471 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
14474 | DBUG_EXECUTE_IF("rocksdb_create_table", { |
| 8509 | THD *const thd = my_core::thd_get_current_thd(); | ||
| 8510 | static constexpr char act[] = | ||
| 8511 | "now signal ready_to_mark_cf_dropped_in_create_table " | ||
| 8512 | "wait_for mark_cf_dropped_done_in_create_table"; | ||
| 8513 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 8514 | }); | ||
| 8515 | |||
| 8516 | { | ||
| 8517 |
1/2✓ Branch 0 taken 14474 times.
✗ Branch 1 not taken.
|
14474 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 8518 |
1/2✓ Branch 0 taken 14474 times.
✗ Branch 1 not taken.
|
14474 | err = ddl_manager.put_and_write(m_tbl_def, batch); |
| 8519 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14471 times.
|
14474 | if (err != HA_EXIT_SUCCESS) { |
| 8520 | 3 | goto error; | |
| 8521 | } | ||
| 8522 | |||
| 8523 |
1/2✓ Branch 0 taken 14471 times.
✗ Branch 1 not taken.
|
14471 | err = local_dict_manager->commit(batch); |
| 8524 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14471 times.
|
14471 | if (err != HA_EXIT_SUCCESS) { |
| 8525 | ✗ | goto error; | |
| 8526 | } | ||
| 8527 |
2/2✓ Branch 0 taken 14471 times.
✓ Branch 1 taken 3 times.
|
14474 | } |
| 8528 | |||
| 8529 |
1/2✓ Branch 0 taken 14471 times.
✗ Branch 1 not taken.
|
14471 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 8530 | |||
| 8531 | 244 | error: | |
| 8532 | /* Delete what we have allocated so far */ | ||
| 8533 |
1/2✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
|
244 | delete m_tbl_def; |
| 8534 | 244 | m_tbl_def = nullptr; | |
| 8535 | 244 | m_key_descr_arr = nullptr; | |
| 8536 | |||
| 8537 |
1/2✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
|
244 | DBUG_RETURN(err); |
| 8538 | 14715 | } | |
| 8539 | |||
| 8540 | /** | ||
| 8541 | @brief | ||
| 8542 | create() is called to create a table. The variable name will have the name | ||
| 8543 | of the table. | ||
| 8544 | |||
| 8545 | @details | ||
| 8546 | When create() is called you do not need to worry about | ||
| 8547 | opening the table. Also, the DD table have already been | ||
| 8548 | created so adjusting create_info is not necessary. | ||
| 8549 | |||
| 8550 | Called from handle.cc by ha_create_table(). | ||
| 8551 | |||
| 8552 | @return | ||
| 8553 | HA_EXIT_SUCCESS OK | ||
| 8554 | other HA_ERR error code (can be SE-specific) | ||
| 8555 | |||
| 8556 | @see | ||
| 8557 | ha_create_table() in handle.cc | ||
| 8558 | */ | ||
| 8559 | |||
| 8560 | 14479 | int ha_rocksdb::create(const char *const name, TABLE *const table_arg, | |
| 8561 | HA_CREATE_INFO *const create_info, | ||
| 8562 | dd::Table *table_def) { | ||
| 8563 |
1/2✓ Branch 0 taken 14479 times.
✗ Branch 1 not taken.
|
14479 | DBUG_ENTER_FUNC(); |
| 8564 | |||
| 8565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14479 times.
|
14479 | assert(table_arg != nullptr); |
| 8566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14479 times.
|
14479 | assert(create_info != nullptr); |
| 8567 | |||
| 8568 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 14470 times.
|
14479 | if (unlikely(create_info->data_file_name)) { |
| 8569 | // DATA DIRECTORY is used to create tables under a specific location | ||
| 8570 | // outside the MySQL data directory. We don't support this for MyRocks. | ||
| 8571 | // The `rocksdb_datadir` setting should be used to configure RocksDB data | ||
| 8572 | // directory. | ||
| 8573 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | DBUG_RETURN(HA_ERR_ROCKSDB_TABLE_DATA_DIRECTORY_NOT_SUPPORTED); |
| 8574 | } | ||
| 8575 | |||
| 8576 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14464 times.
|
14470 | if (unlikely(create_info->index_file_name)) { |
| 8577 | // Similar check for INDEX DIRECTORY as well. | ||
| 8578 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_ERR_ROCKSDB_TABLE_INDEX_DIRECTORY_NOT_SUPPORTED); |
| 8579 | } | ||
| 8580 | |||
| 8581 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14464 times.
|
14464 | if (unlikely(create_info->tablespace)) { |
| 8582 | ✗ | my_error(ER_NOT_SUPPORTED_YET, MYF(0), | |
| 8583 | "TABLESPACEs for the RocksDB storage engine"); | ||
| 8584 | ✗ | DBUG_RETURN(HA_WRONG_CREATE_OPTION); | |
| 8585 | } | ||
| 8586 | |||
| 8587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14464 times.
|
14464 | if (unlikely(create_info->compress.length)) { |
| 8588 | ✗ | my_error(ER_NOT_SUPPORTED_YET, MYF(0), | |
| 8589 | "InnoDB page COMPRESSION for the RocksDB storage engine"); | ||
| 8590 | ✗ | DBUG_RETURN(HA_WRONG_CREATE_OPTION); | |
| 8591 | } | ||
| 8592 | |||
| 8593 |
4/4✓ Branch 0 taken 94 times.
✓ Branch 1 taken 14370 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 14460 times.
|
14558 | if (unlikely(create_info->options & HA_LEX_CREATE_TMP_TABLE) && |
| 8594 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 90 times.
|
94 | !rocksdb_enable_tmp_table) { |
| 8595 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), |
| 8596 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ha_resolve_storage_engine_name(create_info->db_type), "TEMPORARY"); |
| 8597 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | DBUG_RETURN(HA_ERR_ROCKSDB_INVALID_TABLE); |
| 8598 | } | ||
| 8599 | |||
| 8600 | int err; | ||
| 8601 | /* | ||
| 8602 | Construct dbname.tablename ourselves, because parititioning | ||
| 8603 | passes strings like "./test/t14#P#p0" for individual partitions, | ||
| 8604 | while table_arg->s->table_name has none of that. | ||
| 8605 | */ | ||
| 8606 | 14460 | std::string str; | |
| 8607 |
2/4✓ Branch 0 taken 14460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14460 times.
✗ Branch 3 not taken.
|
14460 | err = rdb_normalize_tablename(name, &str); |
| 8608 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14460 times.
|
14460 | if (err != HA_EXIT_SUCCESS) { |
| 8609 | ✗ | DBUG_RETURN(err); | |
| 8610 | } | ||
| 8611 | |||
| 8612 | // FOREIGN KEY isn't supported yet | ||
| 8613 |
1/2✓ Branch 0 taken 14460 times.
✗ Branch 1 not taken.
|
14460 | THD *const thd = my_core::thd_get_current_thd(); |
| 8614 |
3/4✓ Branch 0 taken 14460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 14448 times.
|
14460 | if (contains_foreign_key(thd)) { |
| 8615 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | my_error(ER_NOT_SUPPORTED_YET, MYF(0), |
| 8616 | "FOREIGN KEY for the RocksDB storage engine"); | ||
| 8617 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | DBUG_RETURN(HA_ERR_UNSUPPORTED); |
| 8618 | } | ||
| 8619 | |||
| 8620 | // Check whether Data Dictionary contain information | ||
| 8621 |
1/2✓ Branch 0 taken 14448 times.
✗ Branch 1 not taken.
|
14448 | Rdb_tbl_def *old_tbl = ddl_manager.find(str); |
| 8622 |
2/2✓ Branch 0 taken 2230 times.
✓ Branch 1 taken 12218 times.
|
14448 | if (old_tbl != nullptr) { |
| 8623 |
2/2✓ Branch 0 taken 2224 times.
✓ Branch 1 taken 6 times.
|
2230 | if (thd->lex->sql_command == SQLCOM_TRUNCATE) { |
| 8624 |
2/4✓ Branch 0 taken 2224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2221 times.
✗ Branch 3 not taken.
|
2224 | DBUG_RETURN(truncate_table(old_tbl, create_info->actual_user_table_name, |
| 8625 | table_arg, create_info->auto_increment_value, | ||
| 8626 | table_def)); | ||
| 8627 | } else { | ||
| 8628 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_METADATA_INCONSISTENCY, MYF(0), str.c_str()); |
| 8629 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_ERR_ROCKSDB_CORRUPT_DATA); |
| 8630 | } | ||
| 8631 | } | ||
| 8632 |
2/4✓ Branch 0 taken 12218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12218 times.
✗ Branch 3 not taken.
|
12218 | DBUG_RETURN(create_table(str, create_info->actual_user_table_name, table_arg, |
| 8633 | create_info->auto_increment_value, table_def)); | ||
| 8634 | 14457 | } | |
| 8635 | |||
| 8636 | /* | ||
| 8637 | Fast truncates a table by renaming the old table, creating a new one and | ||
| 8638 | restoring or deleting the old table based on the results from creation. | ||
| 8639 | |||
| 8640 | @param tbl_def IN MyRocks's table structure | ||
| 8641 | @param actual_user_table_name IN actual table name in case | ||
| 8642 | @param table_arg IN sql table | ||
| 8643 | @param auto_increment_value IN specified table's auto increment value | ||
| 8644 | |||
| 8645 | @return | ||
| 8646 | HA_EXIT_SUCCESS OK | ||
| 8647 | other HA_ERR error code (can be SE-specific) | ||
| 8648 | */ | ||
| 8649 | 2500 | int ha_rocksdb::truncate_table(Rdb_tbl_def *tbl_def_arg, | |
| 8650 | const std::string &actual_user_table_name, | ||
| 8651 | TABLE *table_arg, ulonglong auto_increment_value, | ||
| 8652 | dd::Table *table_def) { | ||
| 8653 |
1/2✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
|
2500 | DBUG_ENTER_FUNC(); |
| 8654 | |||
| 8655 | /* | ||
| 8656 | Fast table truncation involves deleting the table and then recreating | ||
| 8657 | it. However, it is possible recreating the table fails. In this case, a | ||
| 8658 | table inconsistency might result between SQL and MyRocks where MyRocks is | ||
| 8659 | missing a table. Since table creation involves modifying keys with the | ||
| 8660 | original table name, renaming the original table first, and then renaming | ||
| 8661 | it back in case of creation failure can help restore the pre-truncation | ||
| 8662 | state. | ||
| 8663 | |||
| 8664 | If the server were to crash during truncation, the system will end up with | ||
| 8665 | an inconsistency. Future changes for atomic ddl will resolve this. For now, | ||
| 8666 | if there are any truncation renamed tables found during startup, MyRocks | ||
| 8667 | will automatically remove them. | ||
| 8668 | */ | ||
| 8669 |
1/2✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
|
2500 | std::string orig_tablename = tbl_def_arg->full_tablename(); |
| 8670 | 2500 | std::string dbname, tblname, partition; | |
| 8671 | |||
| 8672 | /* | ||
| 8673 | Rename the table in the data dictionary. Since this thread should be | ||
| 8674 | holding the MDL for this tablename, it is safe to perform these renames | ||
| 8675 | should be locked via MDL, no other process thread be able to access this | ||
| 8676 | table. | ||
| 8677 | */ | ||
| 8678 |
1/2✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
|
2500 | int err = rdb_split_normalized_tablename(orig_tablename, &dbname, &tblname, |
| 8679 | &partition); | ||
| 8680 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2500 times.
|
2500 | assert(err == 0); |
| 8681 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2500 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2500 | if (err != HA_EXIT_SUCCESS) DBUG_RETURN(err); |
| 8682 |
2/4✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2500 times.
✗ Branch 3 not taken.
|
2500 | tblname = std::string(TRUNCATE_TABLE_PREFIX) + tblname; |
| 8683 | |||
| 8684 | 2500 | std::string tmp_tablename; | |
| 8685 |
1/2✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
|
2500 | rdb_gen_normalized_tablename(&dbname, &tblname, &partition, &tmp_tablename); |
| 8686 | |||
| 8687 |
1/2✓ Branch 0 taken 2500 times.
✗ Branch 1 not taken.
|
2500 | err = rename_table(orig_tablename.c_str(), tmp_tablename.c_str(), table_def, |
| 8688 | table_def); | ||
| 8689 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2500 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2500 | if (err != HA_EXIT_SUCCESS) DBUG_RETURN(err); |
| 8690 | |||
| 8691 | /* | ||
| 8692 | Attempt to create the table. If this succeeds, then drop the old table. | ||
| 8693 | Otherwise, try to restore it. | ||
| 8694 | */ | ||
| 8695 |
1/2✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
|
2500 | err = create_table(orig_tablename, actual_user_table_name, table_arg, |
| 8696 | auto_increment_value, table_def); | ||
| 8697 | 2497 | bool should_remove_old_table = true; | |
| 8698 | |||
| 8699 | /* Restore the old table being truncated if creating the new table failed */ | ||
| 8700 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2488 times.
|
2497 | if (err != HA_EXIT_SUCCESS) { |
| 8701 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | int rename_err = rename_table(tmp_tablename.c_str(), orig_tablename.c_str(), |
| 8702 | table_def, table_def); | ||
| 8703 | |||
| 8704 | /* | ||
| 8705 | If the rename also fails, we are out of options, but at least try to drop | ||
| 8706 | the old table contents. | ||
| 8707 | */ | ||
| 8708 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (rename_err == HA_EXIT_SUCCESS) { |
| 8709 | 9 | should_remove_old_table = false; | |
| 8710 | } else { | ||
| 8711 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 8712 | "Failure during truncation of table %s " | ||
| 8713 | "being renamed from %s", | ||
| 8714 | orig_tablename.c_str(), tmp_tablename.c_str()); | ||
| 8715 | ✗ | err = rename_err; | |
| 8716 | } | ||
| 8717 | } | ||
| 8718 | |||
| 8719 | /* | ||
| 8720 | Since the table was successfully truncated or the name restore failed, no | ||
| 8721 | error should be returned at this point from trying to delete the old | ||
| 8722 | table. If the delete_table fails, log it instead. | ||
| 8723 | */ | ||
| 8724 |
1/2✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
|
2497 | Rdb_tbl_def *old_tbl_def = ddl_manager.find(tmp_tablename); |
| 8725 |
3/4✓ Branch 0 taken 2488 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2488 times.
✗ Branch 3 not taken.
|
2497 | if (should_remove_old_table && old_tbl_def) { |
| 8726 | 2488 | m_tbl_def = old_tbl_def; | |
| 8727 |
2/4✓ Branch 0 taken 2488 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2488 times.
|
2488 | if (delete_table(old_tbl_def) != HA_EXIT_SUCCESS) { |
| 8728 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 8729 | "Failure when trying to drop table %s during " | ||
| 8730 | "truncation of table %s", | ||
| 8731 | tmp_tablename.c_str(), orig_tablename.c_str()); | ||
| 8732 | } | ||
| 8733 | } | ||
| 8734 | |||
| 8735 | /* Update the local m_tbl_def reference */ | ||
| 8736 |
1/2✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
|
2497 | m_tbl_def = ddl_manager.find(orig_tablename); |
| 8737 |
3/6✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2497 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2497 times.
✗ Branch 5 not taken.
|
2497 | m_converter.reset(new Rdb_converter(ha_thd(), m_tbl_def, table_arg)); |
| 8738 |
1/2✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
|
2497 | DBUG_RETURN(err); |
| 8739 | 2497 | } | |
| 8740 | |||
| 8741 | /** | ||
| 8742 | @note | ||
| 8743 | This function is used only when the table has not yet been opened, and | ||
| 8744 | keyread_allowed bitmap doesn't have the correct values yet. | ||
| 8745 | |||
| 8746 | See comment in ha_rocksdb::index_flags() for details. | ||
| 8747 | */ | ||
| 8748 | |||
| 8749 | 2190307 | bool ha_rocksdb::check_keyread_allowed(bool &pk_can_be_decoded, | |
| 8750 | const TABLE_SHARE *, uint, uint, bool) { | ||
| 8751 | /* | ||
| 8752 | (TODO) Remove this function and index version checks, Also remove return | ||
| 8753 | code from Rdb_field_packing:setup() and remove the changes for '[mysql80] | ||
| 8754 | Issue #108: Index-only scans do not work for partitioned tables and | ||
| 8755 | extended keys'. | ||
| 8756 | |||
| 8757 | For the cases of `create table t1 (a varchar(64), key (a(32)))` | ||
| 8758 | and text/blob key columns, the sql layer seems to handle them | ||
| 8759 | correctly regarding using index. InnoDB also seems to return | ||
| 8760 | HA_KEYREAD_ONLY for these cases. | ||
| 8761 | */ | ||
| 8762 | 2190307 | pk_can_be_decoded = true; | |
| 8763 | 2190307 | return true; | |
| 8764 | } | ||
| 8765 | |||
| 8766 | /** | ||
| 8767 | @note | ||
| 8768 | The problem with this function is that SQL layer calls it, when | ||
| 8769 | - the table has not been yet opened (no ::open() call done) | ||
| 8770 | - this->table_share already exists, but it is in the process of being | ||
| 8771 | filled, so some of fields are still NULL. | ||
| 8772 | - In particular, table_share->key_info[inx].key_part[] is filled only up | ||
| 8773 | to part #part. Subsequent key parts are not yet filled. | ||
| 8774 | |||
| 8775 | To complicate things further, SQL layer will call index_flags() with | ||
| 8776 | all_parts=true. Essentially, we're asked to provide flags for reading | ||
| 8777 | keyparts whose datatype is not yet known. | ||
| 8778 | |||
| 8779 | We walk around this problem by using check_keyread_allowed(), which uses | ||
| 8780 | table_share object and is careful not to step on unitialized data. | ||
| 8781 | |||
| 8782 | When we get a call with all_parts=true, we try to analyze all parts but | ||
| 8783 | ignore those that have key_part->field==nullptr (these are not initialized | ||
| 8784 | yet). | ||
| 8785 | */ | ||
| 8786 | |||
| 8787 | 2173362 | ulong ha_rocksdb::index_flags(bool &pk_can_be_decoded, | |
| 8788 | const TABLE_SHARE *table_share, uint inx, | ||
| 8789 | uint part, bool all_parts) { | ||
| 8790 |
1/2✓ Branch 0 taken 2173362 times.
✗ Branch 1 not taken.
|
2173362 | DBUG_ENTER_FUNC(); |
| 8791 | |||
| 8792 | 2173362 | ulong base_flags = HA_READ_NEXT | // doesn't seem to be used | |
| 8793 | HA_READ_ORDER | HA_READ_RANGE | HA_READ_PREV; | ||
| 8794 |
1/2✓ Branch 0 taken 2173362 times.
✗ Branch 1 not taken.
|
2173362 | bool res = check_keyread_allowed(pk_can_be_decoded, table_share, inx, part, |
| 8795 | all_parts); | ||
| 8796 |
1/2✓ Branch 0 taken 2173362 times.
✗ Branch 1 not taken.
|
2173362 | if (res) base_flags |= HA_KEYREAD_ONLY; |
| 8797 | |||
| 8798 |
2/2✓ Branch 0 taken 1665470 times.
✓ Branch 1 taken 507892 times.
|
2173362 | if (inx == table_share->primary_key) { |
| 8799 | /* | ||
| 8800 | Index-only reads on primary key are the same as table scan for us. Still, | ||
| 8801 | we need to explicitly "allow" them, otherwise SQL layer will miss some | ||
| 8802 | plans. | ||
| 8803 | */ | ||
| 8804 | 1665470 | base_flags |= HA_KEYREAD_ONLY; | |
| 8805 |
1/2✓ Branch 0 taken 507892 times.
✗ Branch 1 not taken.
|
507892 | } else if (res) { |
| 8806 | /* We can do ICP only if we are able to decode the key (res == true) */ | ||
| 8807 | /* | ||
| 8808 | We can Index Condition Pushdown any key except the primary. With primary | ||
| 8809 | key, we get (pk, record) pair immediately, there is no place to put the | ||
| 8810 | ICP check. | ||
| 8811 | */ | ||
| 8812 | 507892 | base_flags |= HA_DO_INDEX_COND_PUSHDOWN; | |
| 8813 | } | ||
| 8814 | |||
| 8815 |
1/2✓ Branch 0 taken 2173362 times.
✗ Branch 1 not taken.
|
2173362 | DBUG_RETURN(base_flags); |
| 8816 | } | ||
| 8817 | |||
| 8818 | 2129604 | ulong ha_rocksdb::index_flags(uint inx, uint part, bool all_parts) const { | |
| 8819 | 2129604 | return index_flags(m_pk_can_be_decoded, table_share, inx, part, all_parts); | |
| 8820 | } | ||
| 8821 | |||
| 8822 | /** | ||
| 8823 | @brief | ||
| 8824 | Read from primary key if secondary key is not covering. | ||
| 8825 | |||
| 8826 | @details | ||
| 8827 | m_scan_it points at the index key-value pair that we should read the (pk,row) | ||
| 8828 | pair for. | ||
| 8829 | */ | ||
| 8830 | 52475729 | int ha_rocksdb::secondary_index_read(const int keyno, uchar *const buf, | |
| 8831 | const rocksdb::Slice *value, | ||
| 8832 | bool *skip_row) { | ||
| 8833 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52475729 times.
|
52475729 | assert(buf != nullptr); |
| 8834 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52475729 times.
|
52475729 | assert(table != nullptr); |
| 8835 | |||
| 8836 | 52475729 | int rc = 0; | |
| 8837 | |||
| 8838 | #ifndef NDEBUG | ||
| 8839 | 52475729 | bool save_keyread_only = m_keyread_only; | |
| 8840 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52475726 times.
|
52475729 | DBUG_EXECUTE_IF("dbug.rocksdb.HA_EXTRA_KEYREAD", { m_keyread_only = true; }); |
| 8841 | #endif | ||
| 8842 | bool covered_lookup = | ||
| 8843 |
4/4✓ Branch 0 taken 40350427 times.
✓ Branch 1 taken 12125302 times.
✓ Branch 2 taken 9431 times.
✓ Branch 3 taken 40340996 times.
|
64610462 | (m_keyread_only && m_key_descr_arr[keyno]->can_cover_lookup()) || |
| 8844 |
2/2✓ Branch 0 taken 13323 times.
✓ Branch 1 taken 12121410 times.
|
12134733 | m_key_descr_arr[keyno]->covers_lookup(value, |
| 8845 | 52475729 | m_converter->get_lookup_bitmap()); | |
| 8846 | #ifndef NDEBUG | ||
| 8847 | 52475729 | m_keyread_only = save_keyread_only; | |
| 8848 | #endif | ||
| 8849 | |||
| 8850 |
4/4✓ Branch 0 taken 40354319 times.
✓ Branch 1 taken 12121410 times.
✓ Branch 2 taken 40349069 times.
✓ Branch 3 taken 5250 times.
|
52475729 | if (covered_lookup && m_lock_rows == RDB_LOCK_NONE) { |
| 8851 | 40349069 | inc_covered_sk_lookup(); | |
| 8852 | } else { | ||
| 8853 |
1/2✓ Branch 0 taken 12126660 times.
✗ Branch 1 not taken.
|
12126660 | DEBUG_SYNC(ha_thd(), "rocksdb_concurrent_delete_sk"); |
| 8854 | 12126660 | rc = get_row_by_rowid(buf, m_last_rowkey.ptr(), m_last_rowkey.length(), | |
| 8855 | skip_row); | ||
| 8856 | } | ||
| 8857 | |||
| 8858 | 52475729 | return rc; | |
| 8859 | } | ||
| 8860 | |||
| 8861 | /* | ||
| 8862 | See storage/rocksdb/rocksdb-range-access.txt for description of how MySQL | ||
| 8863 | index navigation commands are converted into RocksDB lookup commands. | ||
| 8864 | |||
| 8865 | MyRocks needs to decide whether prefix bloom filter can be used or not. | ||
| 8866 | To decide to use prefix bloom filter or not, calculating equal condition | ||
| 8867 | length is needed. On equal lookups (find_flag == HA_READ_KEY_EXACT), equal | ||
| 8868 | condition length is the same as rocksdb::Slice.size() of the start key. | ||
| 8869 | On range scan, equal condition length is MIN(start_key, end_key) of the | ||
| 8870 | rocksdb::Slice expression, where end_key is taken from end_range. | ||
| 8871 | |||
| 8872 | @return | ||
| 8873 | HA_EXIT_SUCCESS OK | ||
| 8874 | other HA_ERR error code (can be SE-specific) | ||
| 8875 | */ | ||
| 8876 | 430614 | int ha_rocksdb::index_read_intern(uchar *const buf, const uchar *const key, | |
| 8877 | key_part_map keypart_map, | ||
| 8878 | enum ha_rkey_function find_flag) { | ||
| 8879 |
1/2✓ Branch 0 taken 430614 times.
✗ Branch 1 not taken.
|
430614 | DBUG_ENTER_FUNC(); |
| 8880 | |||
| 8881 |
1/2✓ Branch 0 taken 430614 times.
✗ Branch 1 not taken.
|
430614 | check_build_decoder(); |
| 8882 | |||
| 8883 | 430614 | int rc = 0; | |
| 8884 | 430614 | table->set_no_row(); | |
| 8885 | |||
| 8886 |
1/2✓ Branch 0 taken 430614 times.
✗ Branch 1 not taken.
|
430614 | THD *thd = ha_thd(); |
| 8887 |
2/4✓ Branch 0 taken 430614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 430614 times.
✗ Branch 3 not taken.
|
430614 | DEBUG_SYNC(thd, "rocksdb.check_flags_iri"); |
| 8888 |
5/6✓ Branch 0 taken 430614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 430611 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 430611 times.
|
430614 | if (thd && thd->killed) { |
| 8889 | 3 | rc = HA_ERR_QUERY_INTERRUPTED; | |
| 8890 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(rc); |
| 8891 | } | ||
| 8892 | |||
| 8893 |
1/2✓ Branch 0 taken 430611 times.
✗ Branch 1 not taken.
|
430611 | switch (find_flag) { |
| 8894 | 430611 | case HA_READ_KEY_EXACT: | |
| 8895 | case HA_READ_AFTER_KEY: | ||
| 8896 | case HA_READ_KEY_OR_NEXT: | ||
| 8897 | case HA_READ_BEFORE_KEY: | ||
| 8898 | case HA_READ_PREFIX_LAST: | ||
| 8899 | case HA_READ_PREFIX_LAST_OR_PREV: | ||
| 8900 | 430611 | break; | |
| 8901 | ✗ | default: | |
| 8902 | ✗ | DBUG_RETURN(HA_ERR_UNSUPPORTED); | |
| 8903 | } | ||
| 8904 | |||
| 8905 |
1/2✓ Branch 0 taken 430611 times.
✗ Branch 1 not taken.
|
430611 | const Rdb_key_def &kd = *m_key_descr_arr[active_index_pos()]; |
| 8906 | 430611 | bool using_full_key = false; | |
| 8907 | 430611 | m_full_key_lookup = false; | |
| 8908 | |||
| 8909 | uint packed_size; | ||
| 8910 | |||
| 8911 |
2/2✓ Branch 0 taken 32465 times.
✓ Branch 1 taken 398146 times.
|
430611 | if (!key) { |
| 8912 | // If no key is passed in, then we are doing a full index scan. | ||
| 8913 | // | ||
| 8914 | // Just use current index id as the search key. | ||
| 8915 | 32465 | kd.get_infimum_key(m_sk_packed_tuple, &packed_size); | |
| 8916 | } else { | ||
| 8917 | 398146 | const uint actual_key_parts = kd.get_key_parts(); | |
| 8918 | 398146 | using_full_key = is_using_full_key(keypart_map, actual_key_parts); | |
| 8919 | /* | ||
| 8920 | Handle some special cases when we do exact key lookups. | ||
| 8921 | */ | ||
| 8922 |
4/4✓ Branch 0 taken 388749 times.
✓ Branch 1 taken 9397 times.
✓ Branch 2 taken 167875 times.
✓ Branch 3 taken 220874 times.
|
398146 | if (find_flag == HA_READ_KEY_EXACT && using_full_key) { |
| 8923 |
2/2✓ Branch 0 taken 162835 times.
✓ Branch 1 taken 5040 times.
|
167875 | if (active_index == table->s->primary_key) { |
| 8924 | /* | ||
| 8925 | Equality lookup over primary key, using full tuple. | ||
| 8926 | This is a special case, use DB::Get. | ||
| 8927 | */ | ||
| 8928 |
1/2✓ Branch 0 taken 162835 times.
✗ Branch 1 not taken.
|
162835 | const uint size = kd.pack_index_tuple( |
| 8929 | table, m_pack_buffer, m_pk_packed_tuple, key, keypart_map); | ||
| 8930 |
1/2✓ Branch 0 taken 162835 times.
✗ Branch 1 not taken.
|
162835 | bool skip_lookup = is_blind_delete_enabled(); |
| 8931 | /* TODO(yzha) - row stats are gone in 8.0 | ||
| 8932 | stats.rows_requested++; */ | ||
| 8933 | |||
| 8934 |
1/2✓ Branch 0 taken 162835 times.
✗ Branch 1 not taken.
|
162835 | rc = get_row_by_rowid(buf, m_pk_packed_tuple, size, nullptr, |
| 8935 | skip_lookup, false); | ||
| 8936 |
4/4✓ Branch 0 taken 162493 times.
✓ Branch 1 taken 342 times.
✓ Branch 2 taken 162490 times.
✓ Branch 3 taken 3 times.
|
162835 | if (!rc && !skip_lookup) { |
| 8937 | /* TODO(yzha) - row stats are gone in 8.0 | ||
| 8938 | stats.rows_read++; | ||
| 8939 | stats.rows_index_first++; */ | ||
| 8940 |
1/2✓ Branch 0 taken 162490 times.
✗ Branch 1 not taken.
|
162490 | update_row_stats(ROWS_READ); |
| 8941 | } | ||
| 8942 | /* | ||
| 8943 | If the SQL layer calls index_read_map, it expects the iterator to be | ||
| 8944 | positioned accordingly, so that next/prev can work as expected. In | ||
| 8945 | this case, we calling DB::Get directly without positioning an | ||
| 8946 | iterator, so it is incorrect for the SQL layer to be calling | ||
| 8947 | next/prev anyway. To avoid correctness issues, just free the | ||
| 8948 | iterator. | ||
| 8949 | */ | ||
| 8950 | 162835 | m_full_key_lookup = true; | |
| 8951 |
1/2✓ Branch 0 taken 162835 times.
✗ Branch 1 not taken.
|
162835 | m_iterator->reset(); |
| 8952 |
1/2✓ Branch 0 taken 162835 times.
✗ Branch 1 not taken.
|
162835 | DBUG_RETURN(rc); |
| 8953 | } else { | ||
| 8954 | /* | ||
| 8955 | The SQL layer sometimes sets HA_WHOLE_KEY for secondary keys lookups, | ||
| 8956 | even though it may not include extended keys. | ||
| 8957 | |||
| 8958 | Adjust keypart_map so that we get the correct packing. | ||
| 8959 | */ | ||
| 8960 |
2/2✓ Branch 0 taken 4650 times.
✓ Branch 1 taken 390 times.
|
5040 | if (keypart_map == HA_WHOLE_KEY) { |
| 8961 | 4650 | uint avail_key_parts = 0; | |
| 8962 |
1/2✓ Branch 0 taken 4650 times.
✗ Branch 1 not taken.
|
4650 | calculate_key_len(table, active_index, keypart_map, &avail_key_parts); |
| 8963 | 4650 | keypart_map = make_prev_keypart_map(avail_key_parts); | |
| 8964 | 4650 | using_full_key = is_using_full_key(keypart_map, actual_key_parts); | |
| 8965 | } | ||
| 8966 | |||
| 8967 |
2/2✓ Branch 0 taken 1686 times.
✓ Branch 1 taken 3354 times.
|
5040 | if (table->key_info[active_index].flags & HA_NOSAME && |
| 8968 |
3/4✓ Branch 0 taken 216 times.
✓ Branch 1 taken 1470 times.
✓ Branch 2 taken 216 times.
✗ Branch 3 not taken.
|
1686 | m_insert_with_update && m_dup_key_found && |
| 8969 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | active_index == m_dupp_errkey) { |
| 8970 | /* | ||
| 8971 | We are in INSERT ... ON DUPLICATE KEY UPDATE, and this is a read | ||
| 8972 | that SQL layer does to read the duplicate key. | ||
| 8973 | Its rowid is saved in m_last_rowkey. Get the full record and | ||
| 8974 | return it. | ||
| 8975 | */ | ||
| 8976 | |||
| 8977 | #ifndef NDEBUG | ||
| 8978 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | packed_size = kd.pack_index_tuple( |
| 8979 | table, m_pack_buffer, m_sk_packed_tuple, key, keypart_map); | ||
| 8980 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
|
216 | assert(m_dup_key_tuple.length() >= packed_size); |
| 8981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
|
216 | assert(memcmp(m_dup_key_tuple.ptr(), m_sk_packed_tuple, |
| 8982 | packed_size) == 0); | ||
| 8983 | #endif | ||
| 8984 | |||
| 8985 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | rc = get_row_by_rowid(buf, m_last_rowkey.ptr(), |
| 8986 | 216 | m_last_rowkey.length()); | |
| 8987 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | m_iterator->reset(); |
| 8988 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | DBUG_RETURN(rc); |
| 8989 | } | ||
| 8990 | |||
| 8991 |
2/2✓ Branch 0 taken 390 times.
✓ Branch 1 taken 4434 times.
|
4824 | if (using_full_key) { |
| 8992 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
390 | packed_size = kd.pack_index_tuple( |
| 8993 | table, m_pack_buffer, m_sk_packed_tuple, key, keypart_map); | ||
| 8994 | rocksdb::Slice key_slice( | ||
| 8995 | 390 | reinterpret_cast<const char *>(m_sk_packed_tuple), packed_size); | |
| 8996 | |||
| 8997 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
390 | rc = get_row_by_sk(buf, kd, &key_slice); |
| 8998 | |||
| 8999 |
2/2✓ Branch 0 taken 372 times.
✓ Branch 1 taken 18 times.
|
390 | if (!rc) { |
| 9000 | /* TODO(yzha) - row stats are gone in 8.0 | ||
| 9001 | stats.rows_read++; | ||
| 9002 | stats.rows_index_first++; */ | ||
| 9003 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | update_row_stats(ROWS_READ); |
| 9004 | } | ||
| 9005 | |||
| 9006 | 390 | m_full_key_lookup = true; | |
| 9007 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
390 | m_iterator->reset(); |
| 9008 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
390 | DBUG_RETURN(rc); |
| 9009 | } | ||
| 9010 | } | ||
| 9011 | } | ||
| 9012 | |||
| 9013 |
1/2✓ Branch 0 taken 234705 times.
✗ Branch 1 not taken.
|
234705 | packed_size = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple, |
| 9014 | key, keypart_map); | ||
| 9015 | } | ||
| 9016 | |||
| 9017 | 267170 | rocksdb::Slice slice(reinterpret_cast<const char *>(m_sk_packed_tuple), | |
| 9018 | 267170 | packed_size); | |
| 9019 | |||
| 9020 | 267170 | rocksdb::Slice end_slice; | |
| 9021 |
6/6✓ Branch 0 taken 92852 times.
✓ Branch 1 taken 174318 times.
✓ Branch 2 taken 3845 times.
✓ Branch 3 taken 89007 times.
✓ Branch 4 taken 3826 times.
✓ Branch 5 taken 19 times.
|
267170 | if (end_range && find_flag != HA_READ_KEY_EXACT && |
| 9022 | find_flag != HA_READ_PREFIX_LAST) { | ||
| 9023 | 3826 | uint end_key_packed_size = 0; | |
| 9024 | end_key_packed_size = | ||
| 9025 | 7652 | kd.pack_index_tuple(table, m_pack_buffer, m_end_key_packed_tuple, | |
| 9026 |
1/2✓ Branch 0 taken 3826 times.
✗ Branch 1 not taken.
|
3826 | end_range->key, end_range->keypart_map); |
| 9027 | 3826 | end_slice = | |
| 9028 | 3826 | rocksdb::Slice((char *)m_end_key_packed_tuple, end_key_packed_size); | |
| 9029 | } | ||
| 9030 | |||
| 9031 |
1/2✓ Branch 0 taken 267170 times.
✗ Branch 1 not taken.
|
267170 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); |
| 9032 | 267170 | const bool is_new_snapshot = !tx->has_snapshot(); | |
| 9033 | |||
| 9034 | // Loop as long as we get a deadlock error AND we end up creating the | ||
| 9035 | // snapshot here (i.e. it did not exist prior to this) | ||
| 9036 | for (;;) { | ||
| 9037 |
2/4✓ Branch 0 taken 267191 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 267191 times.
✗ Branch 3 not taken.
|
267191 | DEBUG_SYNC(thd, "rocksdb.check_flags_iri_scan"); |
| 9038 |
5/6✓ Branch 0 taken 267191 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 267188 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 267188 times.
|
267191 | if (thd && thd->killed) { |
| 9039 | 3 | rc = HA_ERR_QUERY_INTERRUPTED; | |
| 9040 | 3 | break; | |
| 9041 | } | ||
| 9042 | /* | ||
| 9043 | This will open the iterator and position it at a record that's equal or | ||
| 9044 | greater than the lookup tuple. | ||
| 9045 | */ | ||
| 9046 |
1/2✓ Branch 0 taken 267188 times.
✗ Branch 1 not taken.
|
267188 | rc = m_iterator->seek(find_flag, slice, using_full_key, end_slice); |
| 9047 | |||
| 9048 |
2/2✓ Branch 0 taken 9792 times.
✓ Branch 1 taken 257396 times.
|
267188 | if (rc) { |
| 9049 | 9792 | break; | |
| 9050 | } | ||
| 9051 | |||
| 9052 | /* | ||
| 9053 | Now get the data for the row into 'buf'. If we were using a primary key | ||
| 9054 | then we have all the rows we need. For a secondary key we now need to | ||
| 9055 | lookup the primary key. | ||
| 9056 | */ | ||
| 9057 |
2/2✓ Branch 0 taken 3992 times.
✓ Branch 1 taken 3675 times.
|
7667 | bool direction = (find_flag == HA_READ_KEY_EXACT) || |
| 9058 |
4/4✓ Branch 0 taken 7667 times.
✓ Branch 1 taken 249729 times.
✓ Branch 2 taken 2607 times.
✓ Branch 3 taken 1385 times.
|
265063 | (find_flag == HA_READ_AFTER_KEY) || |
| 9059 | (find_flag == HA_READ_KEY_OR_NEXT); | ||
| 9060 |
1/2✓ Branch 0 taken 257396 times.
✗ Branch 1 not taken.
|
257396 | rc = index_next_with_direction_intern(buf, direction, true); |
| 9061 | |||
| 9062 |
3/4✓ Branch 0 taken 257396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257375 times.
✓ Branch 3 taken 21 times.
|
257396 | if (!should_recreate_snapshot(rc, is_new_snapshot)) { |
| 9063 | 257375 | break; /* Exit the loop */ | |
| 9064 | } | ||
| 9065 | |||
| 9066 | // release the snapshot and iterator so they will be regenerated | ||
| 9067 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | tx->release_snapshot(); |
| 9068 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | m_iterator->reset(); |
| 9069 | 21 | } | |
| 9070 | |||
| 9071 | if (!rc) { | ||
| 9072 | /* TODO(yzha) - row stats are gone in 8.0 | ||
| 9073 | stats.rows_index_first++; | ||
| 9074 | stats.rows_index_next--; */ | ||
| 9075 | } | ||
| 9076 | |||
| 9077 |
1/2✓ Branch 0 taken 267170 times.
✗ Branch 1 not taken.
|
267170 | DBUG_RETURN(rc); |
| 9078 | } | ||
| 9079 | |||
| 9080 | /* | ||
| 9081 | See storage/rocksdb/rocksdb-range-access.txt for description of how MySQL | ||
| 9082 | index navigation commands are converted into RocksDB lookup commands. | ||
| 9083 | |||
| 9084 | MyRocks needs to decide whether prefix bloom filter can be used or not. | ||
| 9085 | To decide to use prefix bloom filter or not, calculating equal condition | ||
| 9086 | length is needed. On equal lookups (find_flag == HA_READ_KEY_EXACT), equal | ||
| 9087 | condition length is the same as rocksdb::Slice.size() of the start key. | ||
| 9088 | On range scan, equal condition length is MIN(start_key, end_key) of the | ||
| 9089 | rocksdb::Slice expression, where end_key is taken from end_range. | ||
| 9090 | |||
| 9091 | @return | ||
| 9092 | HA_EXIT_SUCCESS OK | ||
| 9093 | other HA_ERR error code (can be SE-specific) | ||
| 9094 | */ | ||
| 9095 | 398149 | int ha_rocksdb::index_read_map(uchar *const buf, const uchar *const key, | |
| 9096 | key_part_map keypart_map, | ||
| 9097 | enum ha_rkey_function find_flag) { | ||
| 9098 |
1/2✓ Branch 0 taken 398149 times.
✗ Branch 1 not taken.
|
398149 | DBUG_ENTER_FUNC(); |
| 9099 |
1/2✓ Branch 0 taken 398149 times.
✗ Branch 1 not taken.
|
398149 | ha_statistic_increment(&System_status_var::ha_read_key_count); |
| 9100 | |||
| 9101 |
1/2✓ Branch 0 taken 398149 times.
✗ Branch 1 not taken.
|
398149 | int rc = index_read_intern(buf, key, keypart_map, find_flag); |
| 9102 | |||
| 9103 | // The SQL layer generally expects HA_ERR_KEY_NOT_FOUND for this call. | ||
| 9104 |
2/2✓ Branch 0 taken 2771 times.
✓ Branch 1 taken 395378 times.
|
398149 | if (rc == HA_ERR_END_OF_FILE) { |
| 9105 | 2771 | rc = HA_ERR_KEY_NOT_FOUND; | |
| 9106 | } | ||
| 9107 | |||
| 9108 |
1/2✓ Branch 0 taken 398149 times.
✗ Branch 1 not taken.
|
398149 | DBUG_RETURN(rc); |
| 9109 | } | ||
| 9110 | |||
| 9111 | /** | ||
| 9112 | @return | ||
| 9113 | HA_EXIT_SUCCESS OK | ||
| 9114 | other HA_ERR error code (can be SE-specific) | ||
| 9115 | */ | ||
| 9116 | 341 | int ha_rocksdb::index_read_last_map(uchar *const buf, const uchar *const key, | |
| 9117 | key_part_map keypart_map) { | ||
| 9118 |
1/2✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
|
341 | DBUG_ENTER_FUNC(); |
| 9119 | |||
| 9120 |
2/4✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
|
682 | DBUG_RETURN(index_read_map(buf, key, keypart_map, HA_READ_PREFIX_LAST)); |
| 9121 | } | ||
| 9122 | |||
| 9123 | /** | ||
| 9124 | @return | ||
| 9125 | HA_ADMIN_OK OK | ||
| 9126 | other HA_ADMIN error code | ||
| 9127 | */ | ||
| 9128 | 123 | int ha_rocksdb::check(THD *const thd, HA_CHECK_OPT *const check_opt) { | |
| 9129 |
1/2✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
|
123 | DBUG_ENTER_FUNC(); |
| 9130 | |||
| 9131 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
|
123 | assert(thd != nullptr); |
| 9132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
|
123 | assert(check_opt != nullptr); |
| 9133 | |||
| 9134 | 123 | const uint pk = table->s->primary_key; | |
| 9135 | 123 | String rowkey_copy; | |
| 9136 | 123 | String sec_key_copy; | |
| 9137 | 123 | const char *const table_name = table->s->table_name.str; | |
| 9138 | |||
| 9139 | // Only when debugging: don't use snapshot when reading | ||
| 9140 | // Rdb_transaction *tx= get_or_create_tx(table->in_use); | ||
| 9141 | // tx->snapshot= nullptr; | ||
| 9142 | |||
| 9143 | bool save_verify_row_debug_checksums = | ||
| 9144 | 123 | m_converter->get_verify_row_debug_checksums(); | |
| 9145 | 123 | m_converter->set_verify_row_debug_checksums(true); | |
| 9146 | /* For each secondary index, check that we can get a PK value from it */ | ||
| 9147 |
9/18✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 123 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 123 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 123 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 123 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 123 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 123 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 123 times.
✗ Branch 17 not taken.
|
123 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "CHECKTABLE %s: Checking table %s", |
| 9148 | table_name, table_name); | ||
| 9149 | 123 | ha_rows row_checksums_at_start = 0; // set/used iff first_index==true | |
| 9150 | 123 | ha_rows row_checksums = ha_rows(-1); | |
| 9151 | 123 | bool first_index = true; | |
| 9152 | |||
| 9153 |
2/2✓ Branch 0 taken 207 times.
✓ Branch 1 taken 123 times.
|
330 | for (uint keyno = 0; keyno < table->s->keys; keyno++) { |
| 9154 |
2/2✓ Branch 0 taken 159 times.
✓ Branch 1 taken 48 times.
|
207 | if (keyno != pk) { |
| 9155 |
1/2✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
|
159 | extra(HA_EXTRA_KEYREAD); |
| 9156 |
1/2✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
|
159 | ha_index_init(keyno, true); |
| 9157 | 159 | ha_rows rows = 0; | |
| 9158 | 159 | m_validated_checksums = 0; | |
| 9159 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 63 times.
|
159 | if (first_index) { |
| 9160 | 96 | row_checksums_at_start = m_converter->get_row_checksums_checked(); | |
| 9161 | } | ||
| 9162 | int res; | ||
| 9163 |
9/18✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 159 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 159 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 159 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 159 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 159 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 159 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 159 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 159 times.
✗ Branch 17 not taken.
|
159 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 9164 | "CHECKTABLE %s: Checking index %s", table_name, | ||
| 9165 | table->key_info[keyno].name); | ||
| 9166 | while (1) { | ||
| 9167 |
2/2✓ Branch 0 taken 159 times.
✓ Branch 1 taken 24531 times.
|
24690 | if (!rows) { |
| 9168 |
1/2✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
|
159 | res = index_first(table->record[0]); |
| 9169 | } else { | ||
| 9170 |
1/2✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
|
24531 | res = index_next(table->record[0]); |
| 9171 | } | ||
| 9172 | |||
| 9173 |
2/2✓ Branch 0 taken 159 times.
✓ Branch 1 taken 24531 times.
|
24690 | if (res == HA_ERR_END_OF_FILE) break; |
| 9174 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24531 times.
|
24531 | if (res) { |
| 9175 | // error | ||
| 9176 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 9177 | "CHECKTABLE %s: .. row %lld: index scan error %d", | ||
| 9178 | table_name, rows, res); | ||
| 9179 | ✗ | goto error; | |
| 9180 | } | ||
| 9181 |
1/2✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
|
24531 | rocksdb::Slice key = m_iterator->key(); |
| 9182 |
1/2✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
|
24531 | sec_key_copy.copy(key.data(), key.size(), &my_charset_bin); |
| 9183 |
1/2✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
|
24531 | rowkey_copy.copy(m_last_rowkey.ptr(), m_last_rowkey.length(), |
| 9184 | &my_charset_bin); | ||
| 9185 | |||
| 9186 |
2/4✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24531 times.
|
24531 | if ((res = get_row_by_rowid(table->record[0], rowkey_copy.ptr(), |
| 9187 | 24531 | rowkey_copy.length()))) { | |
| 9188 | ✗ | LogPluginErrMsg( | |
| 9189 | ERROR_LEVEL, 0, | ||
| 9190 | "CHECKTABLE %s: .. row %lld: failed to fetch row by rowid", | ||
| 9191 | table_name, rows); | ||
| 9192 | ✗ | goto error; | |
| 9193 | } | ||
| 9194 | |||
| 9195 | 24531 | longlong hidden_pk_id = 0; | |
| 9196 |
4/6✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 420 times.
✓ Branch 3 taken 24111 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24531 times.
|
24951 | if (has_hidden_pk(table) && |
| 9197 |
2/4✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 420 times.
|
420 | read_hidden_pk_id_from_rowkey(&hidden_pk_id)) { |
| 9198 | ✗ | goto error; | |
| 9199 | } | ||
| 9200 | |||
| 9201 | /* Check if we get the same PK value */ | ||
| 9202 | 24531 | uint packed_size = m_pk_descr->pack_record( | |
| 9203 |
1/2✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
|
24531 | table, m_pack_buffer, table->record[0], m_pk_packed_tuple, nullptr, |
| 9204 | false, hidden_pk_id); | ||
| 9205 |
2/4✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24531 times.
|
49062 | if (packed_size != rowkey_copy.length() || |
| 9206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24531 times.
|
24531 | memcmp(m_pk_packed_tuple, rowkey_copy.ptr(), packed_size)) { |
| 9207 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 9208 | "CHECKTABLE %s: .. row %lld: PK value mismatch", | ||
| 9209 | table_name, rows); | ||
| 9210 | ✗ | goto print_and_error; | |
| 9211 | } | ||
| 9212 | |||
| 9213 | /* Check if we get the same secondary key value */ | ||
| 9214 | 24531 | packed_size = m_key_descr_arr[keyno]->pack_record( | |
| 9215 |
1/2✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
|
24531 | table, m_pack_buffer, table->record[0], m_sk_packed_tuple, |
| 9216 | &m_sk_tails, false, hidden_pk_id); | ||
| 9217 |
2/4✓ Branch 0 taken 24531 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24531 times.
|
49062 | if (packed_size != sec_key_copy.length() || |
| 9218 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24531 times.
|
24531 | memcmp(m_sk_packed_tuple, sec_key_copy.ptr(), packed_size)) { |
| 9219 | ✗ | LogPluginErrMsg( | |
| 9220 | ERROR_LEVEL, 0, | ||
| 9221 | "CHECKTABLE %s: .. row %lld: secondary index value mismatch", | ||
| 9222 | table_name, rows); | ||
| 9223 | ✗ | goto print_and_error; | |
| 9224 | } | ||
| 9225 | 24531 | rows++; | |
| 9226 | 24531 | continue; | |
| 9227 | |||
| 9228 | ✗ | print_and_error : { | |
| 9229 | ✗ | std::string buf; | |
| 9230 | ✗ | buf = rdb_hexdump(rowkey_copy.ptr(), rowkey_copy.length(), | |
| 9231 | ✗ | RDB_MAX_HEXDUMP_LEN); | |
| 9232 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "CHECKTABLE %s: rowkey: %s", | |
| 9233 | table_name, buf.c_str()); | ||
| 9234 | |||
| 9235 | ✗ | buf = rdb_hexdump(m_retrieved_record.data(), m_retrieved_record.size(), | |
| 9236 | ✗ | RDB_MAX_HEXDUMP_LEN); | |
| 9237 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "CHECKTABLE %s: record: %s", | |
| 9238 | table_name, buf.c_str()); | ||
| 9239 | |||
| 9240 | ✗ | buf = rdb_hexdump(sec_key_copy.ptr(), sec_key_copy.length(), | |
| 9241 | ✗ | RDB_MAX_HEXDUMP_LEN); | |
| 9242 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "CHECKTABLE %s: index: %s", | |
| 9243 | table_name, buf.c_str()); | ||
| 9244 | |||
| 9245 | ✗ | goto error; | |
| 9246 | } | ||
| 9247 | 24531 | } | |
| 9248 |
9/18✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 159 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 159 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 159 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 159 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 159 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 159 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 159 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 159 times.
✗ Branch 17 not taken.
|
159 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 9249 | "CHECKTABLE %s: ... %lld index entries checked (%lld " | ||
| 9250 | "had checksums)", | ||
| 9251 | table_name, rows, m_validated_checksums); | ||
| 9252 | |||
| 9253 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 63 times.
|
159 | if (first_index) { |
| 9254 | 96 | row_checksums = | |
| 9255 | 96 | m_converter->get_row_checksums_checked() - row_checksums_at_start; | |
| 9256 | 96 | first_index = false; | |
| 9257 | } | ||
| 9258 |
1/2✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
|
159 | ha_index_end(); |
| 9259 | } | ||
| 9260 | } | ||
| 9261 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 27 times.
|
123 | if (row_checksums != ha_rows(-1)) { |
| 9262 |
9/18✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 96 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 96 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 96 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 96 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 96 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 96 times.
✗ Branch 17 not taken.
|
96 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 9263 | "CHECKTABLE %s: %lld table records had checksums", | ||
| 9264 | table_name, row_checksums); | ||
| 9265 | } | ||
| 9266 |
1/2✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
|
123 | extra(HA_EXTRA_NO_KEYREAD); |
| 9267 | |||
| 9268 | 123 | m_converter->set_verify_row_debug_checksums(save_verify_row_debug_checksums); | |
| 9269 | /* | ||
| 9270 | TODO: we should check also for PK records that are missing in the secondary | ||
| 9271 | indexes. | ||
| 9272 | For that, need to walk through the PK and check that every PK record has a | ||
| 9273 | proper counterpart in each secondary index. | ||
| 9274 | */ | ||
| 9275 |
1/2✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
|
123 | DBUG_RETURN(HA_ADMIN_OK); |
| 9276 | ✗ | error: | |
| 9277 | ✗ | m_converter->set_verify_row_debug_checksums(save_verify_row_debug_checksums); | |
| 9278 | ✗ | ha_index_or_rnd_end(); | |
| 9279 | ✗ | extra(HA_EXTRA_NO_KEYREAD); | |
| 9280 | |||
| 9281 | ✗ | DBUG_RETURN(HA_ADMIN_CORRUPT); | |
| 9282 | 123 | } | |
| 9283 | |||
| 9284 | ✗ | static void dbug_dump_str(FILE *const out, const char *const str, int len) { | |
| 9285 | ✗ | fprintf(out, "\""); | |
| 9286 | ✗ | for (int i = 0; i < len; i++) { | |
| 9287 | ✗ | if (str[i] > 32) { | |
| 9288 | ✗ | fprintf(out, "%c", str[i]); | |
| 9289 | } else { | ||
| 9290 | ✗ | fprintf(out, "\\%d", str[i]); | |
| 9291 | } | ||
| 9292 | } | ||
| 9293 | ✗ | fprintf(out, "\""); | |
| 9294 | } | ||
| 9295 | |||
| 9296 | /* | ||
| 9297 | Debugging help: dump the whole database into a human-readable file. | ||
| 9298 | Usage: | ||
| 9299 | dbug_dump_database(rdb); | ||
| 9300 | */ | ||
| 9301 | |||
| 9302 | ✗ | void dbug_dump_database(rocksdb::DB *const db) { | |
| 9303 | ✗ | FILE *const out = fopen("/tmp/rocksdb.dump", "wt"); | |
| 9304 | ✗ | if (!out) return; | |
| 9305 | |||
| 9306 | ✗ | rocksdb::Iterator *it = db->NewIterator(rocksdb::ReadOptions()); | |
| 9307 | ✗ | for (it->SeekToFirst(); it->Valid(); it->Next()) { | |
| 9308 | ✗ | rocksdb::Slice key = it->key(); | |
| 9309 | ✗ | rocksdb::Slice val = it->value(); | |
| 9310 | ✗ | dbug_dump_str(out, key.data(), key.size()); | |
| 9311 | ✗ | fprintf(out, " -> "); | |
| 9312 | ✗ | dbug_dump_str(out, val.data(), val.size()); | |
| 9313 | ✗ | fprintf(out, "\n"); | |
| 9314 | } | ||
| 9315 | |||
| 9316 | ✗ | delete it; | |
| 9317 | ✗ | fclose(out); | |
| 9318 | } | ||
| 9319 | |||
| 9320 | 3873 | rocksdb::Status ha_rocksdb::get_for_update(Rdb_transaction *const tx, | |
| 9321 | const Rdb_key_def &key_descr, | ||
| 9322 | const rocksdb::Slice &key) const { | ||
| 9323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3873 times.
|
3873 | assert(m_lock_rows != RDB_LOCK_NONE); |
| 9324 | |||
| 9325 | 3873 | bool exclusive = m_lock_rows != RDB_LOCK_READ; | |
| 9326 | 3873 | bool skip_wait = | |
| 9327 |
2/4✓ Branch 0 taken 3873 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3873 times.
|
3873 | m_locked_row_action == THR_NOWAIT || m_locked_row_action == THR_SKIP; |
| 9328 | return rdb_tx_get_for_update(tx, key_descr, key, nullptr, exclusive, | ||
| 9329 | 3873 | skip_wait); | |
| 9330 | } | ||
| 9331 | |||
| 9332 | 162835 | bool ha_rocksdb::is_blind_delete_enabled() { | |
| 9333 | 162835 | THD *thd = ha_thd(); | |
| 9334 | 162835 | return (THDVAR(thd, blind_delete_primary_key) && | |
| 9335 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | thd->lex->sql_command == SQLCOM_DELETE && |
| 9336 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | thd->lex->table_count == 1 && table->s->keys == 1 && |
| 9337 |
4/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 162832 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
162838 | !has_hidden_pk(table) && !thd->rli_slave); |
| 9338 | } | ||
| 9339 | |||
| 9340 | /* | ||
| 9341 | Given a rowid (i.e. packed PK) as a parameter, get the record. | ||
| 9342 | |||
| 9343 | @return | ||
| 9344 | HA_EXIT_SUCCESS OK | ||
| 9345 | other HA_ERR error code (can be SE-specific) | ||
| 9346 | */ | ||
| 9347 | |||
| 9348 | 16320090 | int ha_rocksdb::get_row_by_rowid(uchar *const buf, const char *const rowid, | |
| 9349 | const uint rowid_size, bool *skip_row, | ||
| 9350 | const bool skip_lookup, | ||
| 9351 | const bool skip_ttl_check) { | ||
| 9352 |
1/2✓ Branch 0 taken 16320090 times.
✗ Branch 1 not taken.
|
16320090 | DBUG_ENTER_FUNC(); |
| 9353 | |||
| 9354 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16320090 times.
|
16320090 | assert(buf != nullptr); |
| 9355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16320090 times.
|
16320090 | assert(rowid != nullptr); |
| 9356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16320090 times.
|
16320090 | assert(table != nullptr); |
| 9357 | |||
| 9358 | int rc; | ||
| 9359 | |||
| 9360 |
2/2✓ Branch 0 taken 16010221 times.
✓ Branch 1 taken 309869 times.
|
16320090 | if (skip_row) { |
| 9361 | 16010221 | *skip_row = false; | |
| 9362 | } | ||
| 9363 | |||
| 9364 | 16320090 | rocksdb::Slice key_slice(rowid, rowid_size); | |
| 9365 | |||
| 9366 |
1/2✓ Branch 0 taken 16320090 times.
✗ Branch 1 not taken.
|
16320090 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); |
| 9367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16320090 times.
|
16320090 | assert(tx != nullptr); |
| 9368 | |||
| 9369 |
3/6✓ Branch 0 taken 16320090 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16320090 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16320090 times.
✗ Branch 5 not taken.
|
16320090 | DEBUG_SYNC(ha_thd(), "rocksdb.get_row_by_rowid"); |
| 9370 |
7/12✓ Branch 0 taken 16320090 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 16320084 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
|
16320090 | DBUG_EXECUTE_IF("dbug.rocksdb.get_row_by_rowid", { |
| 9371 | THD *thd = ha_thd(); | ||
| 9372 | static constexpr char act[] = | ||
| 9373 | "now signal Reached " | ||
| 9374 | "wait_for signal.rocksdb.get_row_by_rowid_let_running"; | ||
| 9375 | assert(opt_debug_sync_timeout > 0); | ||
| 9376 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 9377 | };); | ||
| 9378 | |||
| 9379 | /* Pretend row found without looking up */ | ||
| 9380 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16320087 times.
|
16320090 | if (skip_lookup) { |
| 9381 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | update_row_stats(ROWS_DELETED_BLIND); |
| 9382 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | m_last_rowkey.copy((const char *)rowid, rowid_size, &my_charset_bin); |
| 9383 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(0); |
| 9384 | } | ||
| 9385 | |||
| 9386 |
5/6✓ Branch 0 taken 377 times.
✓ Branch 1 taken 16319710 times.
✓ Branch 2 taken 377 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 161 times.
✓ Branch 5 taken 16319926 times.
|
16320464 | if (m_insert_with_update && m_dup_key_found && |
| 9387 |
2/2✓ Branch 0 taken 161 times.
✓ Branch 1 taken 216 times.
|
377 | m_pk_descr->get_keyno() == m_dupp_errkey) { |
| 9388 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
|
161 | assert(m_lock_rows == RDB_LOCK_WRITE); |
| 9389 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
|
161 | assert(m_dup_key_tuple.length() == key_slice.size()); |
| 9390 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
|
161 | assert( |
| 9391 | memcmp(m_dup_key_tuple.ptr(), key_slice.data(), key_slice.size()) == 0); | ||
| 9392 | |||
| 9393 | // We have stored the record with duplicate key in | ||
| 9394 | // m_dup_key_retrieved_record during write_row already, so just move it | ||
| 9395 | // over. | ||
| 9396 |
1/2✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
|
161 | m_retrieved_record = std::move(m_dup_key_retrieved_record); |
| 9397 | 161 | rc = HA_EXIT_SUCCESS; | |
| 9398 | } else { | ||
| 9399 |
1/2✓ Branch 0 taken 16319926 times.
✗ Branch 1 not taken.
|
16319926 | tx->acquire_snapshot(false); |
| 9400 | 16319926 | bool skip_wait = | |
| 9401 |
4/4✓ Branch 0 taken 16319884 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 16319776 times.
|
16319926 | m_locked_row_action == THR_NOWAIT || m_locked_row_action == THR_SKIP; |
| 9402 |
2/4✓ Branch 0 taken 16319926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16319926 times.
✗ Branch 3 not taken.
|
16319926 | rc = get_pk_iterator()->get(&key_slice, &m_retrieved_record, m_lock_rows, |
| 9403 | skip_ttl_check, skip_wait); | ||
| 9404 | } | ||
| 9405 | |||
| 9406 |
2/2✓ Branch 0 taken 16319473 times.
✓ Branch 1 taken 614 times.
|
16320087 | if (!rc) { |
| 9407 |
1/2✓ Branch 0 taken 16319473 times.
✗ Branch 1 not taken.
|
16319473 | m_last_rowkey.copy((const char *)rowid, rowid_size, &my_charset_bin); |
| 9408 |
1/2✓ Branch 0 taken 16319473 times.
✗ Branch 1 not taken.
|
16319473 | rc = convert_record_from_storage_format(&key_slice, buf); |
| 9409 | |||
| 9410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16319473 times.
|
16319473 | if (rc) { |
| 9411 | ✗ | DBUG_RETURN(rc); | |
| 9412 | } | ||
| 9413 | |||
| 9414 |
1/2✓ Branch 0 taken 16319473 times.
✗ Branch 1 not taken.
|
16319473 | rc = fill_virtual_columns(); |
| 9415 |
3/4✓ Branch 0 taken 614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 569 times.
|
614 | } else if (should_skip_locked_record(rc)) { |
| 9416 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | if (skip_row) { |
| 9417 | 45 | *skip_row = true; | |
| 9418 | } | ||
| 9419 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); |
| 9420 | } | ||
| 9421 | |||
| 9422 | /* | ||
| 9423 | Note: we don't need to unlock the row. It is intentional that we keep | ||
| 9424 | locks on rows that don't exist. | ||
| 9425 | */ | ||
| 9426 |
1/2✓ Branch 0 taken 16320042 times.
✗ Branch 1 not taken.
|
16320042 | DBUG_RETURN(rc); |
| 9427 | } | ||
| 9428 | |||
| 9429 | 600 | int ha_rocksdb::records(ha_rows *num_rows) { | |
| 9430 |
2/2✓ Branch 0 taken 591 times.
✓ Branch 1 taken 9 times.
|
600 | if (m_lock_rows == RDB_LOCK_NONE) { |
| 9431 | // SELECT COUNT(*) without locking, fast path | ||
| 9432 | 591 | m_iteration_only = true; | |
| 9433 | auto iteration_guard = | ||
| 9434 |
1/2✓ Branch 0 taken 591 times.
✗ Branch 1 not taken.
|
591 | create_scope_guard([this]() { m_iteration_only = false; }); |
| 9435 |
1/2✓ Branch 0 taken 591 times.
✗ Branch 1 not taken.
|
591 | return handler::records(num_rows); |
| 9436 | 591 | } else { | |
| 9437 | // SELECT COUNT(*) with locking, slow path | ||
| 9438 | 9 | return handler::records(num_rows); | |
| 9439 | } | ||
| 9440 | } | ||
| 9441 | |||
| 9442 | 721 | int ha_rocksdb::records_from_index(ha_rows *num_rows, uint index) { | |
| 9443 |
2/2✓ Branch 0 taken 712 times.
✓ Branch 1 taken 9 times.
|
721 | if (m_lock_rows == RDB_LOCK_NONE) { |
| 9444 | // SELECT COUNT(*) without locking, fast path | ||
| 9445 | 712 | m_iteration_only = true; | |
| 9446 | auto iteration_guard = | ||
| 9447 |
1/2✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
|
712 | create_scope_guard([this]() { m_iteration_only = false; }); |
| 9448 |
1/2✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
|
712 | return handler::records_from_index(num_rows, index); |
| 9449 | 712 | } else { | |
| 9450 | // SELECT COUNT(*) with locking, slow path | ||
| 9451 | 9 | return handler::records_from_index(num_rows, index); | |
| 9452 | } | ||
| 9453 | } | ||
| 9454 | |||
| 9455 | /* | ||
| 9456 | The analagous function to ha_rocksdb::get_row_by_rowid for performing | ||
| 9457 | secondary key lookups. | ||
| 9458 | |||
| 9459 | @return | ||
| 9460 | HA_EXIT_SUCCESS OK | ||
| 9461 | other HA_ERR error code (can be SE-specific) | ||
| 9462 | */ | ||
| 9463 | 390 | int ha_rocksdb::get_row_by_sk(uchar *buf, const Rdb_key_def &kd, | |
| 9464 | const rocksdb::Slice *key) { | ||
| 9465 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
390 | DBUG_ENTER_FUNC(); |
| 9466 | |||
| 9467 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
390 | int rc = m_iterator->get(key, &m_retrieved_record, RDB_LOCK_NONE); |
| 9468 |
3/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 372 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
390 | if (rc) DBUG_RETURN(rc); |
| 9469 | |||
| 9470 | const uint size = | ||
| 9471 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | kd.get_primary_key_tuple(*m_pk_descr, key, m_pk_packed_tuple); |
| 9472 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | if (size == RDB_INVALID_KEY_LEN) { |
| 9473 | ✗ | DBUG_RETURN(HA_ERR_ROCKSDB_CORRUPT_DATA); | |
| 9474 | } | ||
| 9475 | |||
| 9476 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | m_last_rowkey.copy((const char *)m_pk_packed_tuple, size, &my_charset_bin); |
| 9477 | |||
| 9478 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | rc = secondary_index_read(active_index, buf, &m_retrieved_record, nullptr); |
| 9479 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | if (!rc) { |
| 9480 | 372 | table->set_found_row(); | |
| 9481 | } | ||
| 9482 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | DBUG_RETURN(rc); |
| 9483 | } | ||
| 9484 | |||
| 9485 | /** | ||
| 9486 | @return | ||
| 9487 | HA_EXIT_SUCCESS OK | ||
| 9488 | other HA_ERR error code (can be SE-specific) | ||
| 9489 | */ | ||
| 9490 | 88945623 | int ha_rocksdb::index_next(uchar *const buf) { | |
| 9491 |
1/2✓ Branch 0 taken 88945623 times.
✗ Branch 1 not taken.
|
88945623 | DBUG_ENTER_FUNC(); |
| 9492 | |||
| 9493 |
1/2✓ Branch 0 taken 88945623 times.
✗ Branch 1 not taken.
|
88945623 | check_build_decoder(); |
| 9494 | |||
| 9495 |
1/2✓ Branch 0 taken 88945623 times.
✗ Branch 1 not taken.
|
88945623 | ha_statistic_increment(&System_status_var::ha_read_next_count); |
| 9496 |
2/4✓ Branch 0 taken 88945623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88945623 times.
✗ Branch 3 not taken.
|
177891246 | DBUG_RETURN(index_next_with_direction_intern(buf, true, false)); |
| 9497 | } | ||
| 9498 | |||
| 9499 | /** | ||
| 9500 | @return | ||
| 9501 | HA_EXIT_SUCCESS OK | ||
| 9502 | other HA_ERR error code (can be SE-specific) | ||
| 9503 | */ | ||
| 9504 | 371663 | int ha_rocksdb::index_next_same(uchar *const buf, | |
| 9505 | const uchar *key MY_ATTRIBUTE((unused)), | ||
| 9506 | uint keylen MY_ATTRIBUTE((unused))) { | ||
| 9507 |
1/2✓ Branch 0 taken 371663 times.
✗ Branch 1 not taken.
|
371663 | DBUG_ENTER_FUNC(); |
| 9508 | |||
| 9509 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 371657 times.
|
371663 | if (m_full_key_lookup) { |
| 9510 | #ifndef NDEBUG | ||
| 9511 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | uint len = calculate_key_len(table, active_index, HA_WHOLE_KEY); |
| 9512 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(len == keylen); |
| 9513 | #endif | ||
| 9514 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
| 9515 | } | ||
| 9516 |
2/4✓ Branch 0 taken 371657 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 371657 times.
✗ Branch 3 not taken.
|
371657 | DBUG_RETURN(index_next(buf)); |
| 9517 | } | ||
| 9518 | |||
| 9519 | /** | ||
| 9520 | @return | ||
| 9521 | HA_EXIT_SUCCESS OK | ||
| 9522 | other HA_ERR error code (can be SE-specific) | ||
| 9523 | */ | ||
| 9524 | 93386 | int ha_rocksdb::index_prev(uchar *const buf) { | |
| 9525 |
1/2✓ Branch 0 taken 93386 times.
✗ Branch 1 not taken.
|
93386 | DBUG_ENTER_FUNC(); |
| 9526 | |||
| 9527 |
1/2✓ Branch 0 taken 93386 times.
✗ Branch 1 not taken.
|
93386 | check_build_decoder(); |
| 9528 | |||
| 9529 |
1/2✓ Branch 0 taken 93386 times.
✗ Branch 1 not taken.
|
93386 | ha_statistic_increment(&System_status_var::ha_read_prev_count); |
| 9530 |
2/4✓ Branch 0 taken 93386 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93386 times.
✗ Branch 3 not taken.
|
186772 | DBUG_RETURN(index_next_with_direction_intern(buf, false, false)); |
| 9531 | } | ||
| 9532 | |||
| 9533 | /** | ||
| 9534 | This function handles all the logic for reading out the next row given a valid | ||
| 9535 | iterator, and populates buf with the next row on success. This includes | ||
| 9536 | filtering logic (eg. ICP, TTL, etc.), locking and reading from the PK to | ||
| 9537 | obtain full row if necessary. | ||
| 9538 | |||
| 9539 | The skip_next parameter determines whether we need to advance the iterator at | ||
| 9540 | least once. Generally, callers that are seeking (eg. | ||
| 9541 | index_first/index_read_map/etc.) will set skip_next to true, since the | ||
| 9542 | iterator is already at the correct position and may not need advancement. | ||
| 9543 | Callers that are iterating to the next key (eg. index_next/index_prev/etc.) | ||
| 9544 | will set skip_next to false since the iterator needs to be advanced at least | ||
| 9545 | once. | ||
| 9546 | |||
| 9547 | The move_forward parameter controls the direction of iteration. | ||
| 9548 | |||
| 9549 | @return | ||
| 9550 | HA_EXIT_SUCCESS OK | ||
| 9551 | other HA_ERR error code (can be SE-specific) | ||
| 9552 | */ | ||
| 9553 | 186325145 | int ha_rocksdb::index_next_with_direction_intern(uchar *const buf, | |
| 9554 | bool move_forward, | ||
| 9555 | bool skip_next) { | ||
| 9556 |
1/2✓ Branch 0 taken 186325145 times.
✗ Branch 1 not taken.
|
186325145 | DBUG_ENTER_FUNC(); |
| 9557 | |||
| 9558 |
1/2✓ Branch 0 taken 186325145 times.
✗ Branch 1 not taken.
|
186325145 | THD *thd = ha_thd(); |
| 9559 | 186325145 | int rc = 0; | |
| 9560 |
1/2✓ Branch 0 taken 186325145 times.
✗ Branch 1 not taken.
|
186325145 | const Rdb_key_def &kd = *m_key_descr_arr[active_index_pos()]; |
| 9561 | |||
| 9562 | 186325145 | table->set_no_row(); | |
| 9563 | /* TODO(yzha) - row stats are gone in 8.0 | ||
| 9564 | stats.rows_requested++; */ | ||
| 9565 | |||
| 9566 | for (;;) { | ||
| 9567 |
2/4✓ Branch 0 taken 186325478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186325478 times.
✗ Branch 3 not taken.
|
186325478 | DEBUG_SYNC(thd, "rocksdb.check_flags_inwdi"); |
| 9568 |
5/6✓ Branch 0 taken 186325478 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 186325472 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 186325472 times.
|
186325478 | if (thd && thd->killed) { |
| 9569 | 6 | rc = HA_ERR_QUERY_INTERRUPTED; | |
| 9570 | 6 | break; | |
| 9571 | } | ||
| 9572 | |||
| 9573 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 186325472 times.
|
186325472 | assert(m_iterator != nullptr); |
| 9574 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 186325472 times.
|
186325472 | if (m_iterator == nullptr) { |
| 9575 | ✗ | rc = HA_ERR_INTERNAL_ERROR; | |
| 9576 | ✗ | break; | |
| 9577 | } | ||
| 9578 | |||
| 9579 |
2/2✓ Branch 0 taken 257390 times.
✓ Branch 1 taken 186068082 times.
|
186325472 | if (skip_next) { |
| 9580 | 257390 | skip_next = false; | |
| 9581 | } else { | ||
| 9582 |
2/2✓ Branch 0 taken 161943964 times.
✓ Branch 1 taken 24124118 times.
|
186068082 | if (move_forward) { |
| 9583 |
1/2✓ Branch 0 taken 161943964 times.
✗ Branch 1 not taken.
|
161943964 | rc = m_iterator->next(); |
| 9584 | } else { | ||
| 9585 |
1/2✓ Branch 0 taken 24124118 times.
✗ Branch 1 not taken.
|
24124118 | rc = m_iterator->prev(); |
| 9586 | } | ||
| 9587 | } | ||
| 9588 | |||
| 9589 |
2/2✓ Branch 0 taken 241327 times.
✓ Branch 1 taken 186084145 times.
|
186325472 | if (rc) { |
| 9590 | 241327 | break; | |
| 9591 | } | ||
| 9592 | |||
| 9593 |
1/2✓ Branch 0 taken 186084145 times.
✗ Branch 1 not taken.
|
186084145 | const rocksdb::Slice &key = m_iterator->key(); |
| 9594 |
1/2✓ Branch 0 taken 186084145 times.
✗ Branch 1 not taken.
|
186084145 | const rocksdb::Slice &value = m_iterator->value(); |
| 9595 | |||
| 9596 |
2/2✓ Branch 0 taken 58270514 times.
✓ Branch 1 taken 127813631 times.
|
186084145 | if (m_iteration_only) { |
| 9597 | 58270514 | table->set_found_row(); | |
| 9598 | 58270514 | rc = 0; | |
| 9599 |
2/2✓ Branch 0 taken 75337678 times.
✓ Branch 1 taken 52475953 times.
|
127813631 | } else if (active_index == table->s->primary_key) { |
| 9600 |
2/2✓ Branch 0 taken 3883573 times.
✓ Branch 1 taken 71454105 times.
|
75337678 | if (m_lock_rows != RDB_LOCK_NONE) { |
| 9601 |
3/6✓ Branch 0 taken 3883573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3883573 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3883573 times.
✗ Branch 5 not taken.
|
3883573 | DEBUG_SYNC(ha_thd(), "rocksdb_concurrent_delete"); |
| 9602 | /* We need to put a lock and re-read */ | ||
| 9603 | 3883573 | bool skip_row = false; | |
| 9604 |
1/2✓ Branch 0 taken 3883573 times.
✗ Branch 1 not taken.
|
3883573 | rc = get_row_by_rowid(buf, key.data(), key.size(), &skip_row); |
| 9605 |
4/4✓ Branch 0 taken 197 times.
✓ Branch 1 taken 3883376 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 161 times.
|
3883573 | if (rc != HA_EXIT_SUCCESS && skip_row) { |
| 9606 | // We are asked to skip locked rows | ||
| 9607 | 36 | continue; | |
| 9608 | } | ||
| 9609 | } else { | ||
| 9610 | /* Unpack from the row we've read */ | ||
| 9611 |
1/2✓ Branch 0 taken 71454105 times.
✗ Branch 1 not taken.
|
71454105 | m_last_rowkey.copy(key.data(), key.size(), &my_charset_bin); |
| 9612 |
1/2✓ Branch 0 taken 71454105 times.
✗ Branch 1 not taken.
|
71454105 | rc = convert_record_from_storage_format(&key, &value, buf); |
| 9613 | } | ||
| 9614 | } else { | ||
| 9615 |
1/2✓ Branch 0 taken 52475953 times.
✗ Branch 1 not taken.
|
52475953 | rc = kd.unpack_record(table, buf, &key, &value, |
| 9616 | 52475953 | m_converter->get_verify_row_debug_checksums()); | |
| 9617 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52475941 times.
|
52475953 | if (rc != HA_EXIT_SUCCESS) { |
| 9618 | 377 | break; | |
| 9619 | } | ||
| 9620 | |||
| 9621 | // Record did not satisfy ICP, move to next record | ||
| 9622 |
3/4✓ Branch 0 taken 46503 times.
✓ Branch 1 taken 52429438 times.
✓ Branch 2 taken 46503 times.
✗ Branch 3 not taken.
|
52475941 | if (pushed_idx_cond && pushed_idx_cond_keyno == active_index) { |
| 9623 |
1/2✓ Branch 0 taken 46503 times.
✗ Branch 1 not taken.
|
46503 | const enum icp_result icp_status = check_index_cond(); |
| 9624 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 46284 times.
|
46503 | if (icp_status == ICP_NO_MATCH) { |
| 9625 | 219 | continue; | |
| 9626 |
2/2✓ Branch 0 taken 365 times.
✓ Branch 1 taken 45919 times.
|
46284 | } else if (icp_status == ICP_OUT_OF_RANGE) { |
| 9627 | 365 | rc = HA_ERR_END_OF_FILE; | |
| 9628 | 365 | break; | |
| 9629 | } | ||
| 9630 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45919 times.
|
45919 | assert(icp_status == ICP_MATCH); |
| 9631 | } | ||
| 9632 | |||
| 9633 | const uint size = | ||
| 9634 |
1/2✓ Branch 0 taken 52475357 times.
✗ Branch 1 not taken.
|
52475357 | kd.get_primary_key_tuple(*m_pk_descr, &key, m_pk_packed_tuple); |
| 9635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52475357 times.
|
52475357 | if (size == RDB_INVALID_KEY_LEN) { |
| 9636 | ✗ | rc = HA_ERR_ROCKSDB_CORRUPT_DATA; | |
| 9637 | ✗ | break; | |
| 9638 | } | ||
| 9639 | |||
| 9640 |
1/2✓ Branch 0 taken 52475357 times.
✗ Branch 1 not taken.
|
52475357 | m_last_rowkey.copy((const char *)m_pk_packed_tuple, size, |
| 9641 | &my_charset_bin); | ||
| 9642 | |||
| 9643 | 52475357 | bool skip_row = false; | |
| 9644 |
1/2✓ Branch 0 taken 52475357 times.
✗ Branch 1 not taken.
|
52475357 | rc = secondary_index_read(active_index, buf, &value, &skip_row); |
| 9645 |
3/4✓ Branch 0 taken 52475291 times.
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 52475291 times.
|
52475357 | if (!rc && skip_row) { |
| 9646 | // SKIP LOCKED | ||
| 9647 | ✗ | continue; | |
| 9648 | } | ||
| 9649 | } | ||
| 9650 | |||
| 9651 |
3/4✓ Branch 0 taken 186083513 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186083435 times.
✓ Branch 3 taken 78 times.
|
186083513 | if (!should_skip_invalidated_record(rc)) { |
| 9652 | 186083435 | break; | |
| 9653 | } | ||
| 9654 | 333 | } | |
| 9655 | |||
| 9656 |
2/2✓ Branch 0 taken 186083274 times.
✓ Branch 1 taken 241871 times.
|
186325145 | if (!rc) { |
| 9657 | /* TODO(yzha) - row stats are gone in 8.0 | ||
| 9658 | stats.rows_read++; | ||
| 9659 | stats.rows_index_next++; */ | ||
| 9660 |
1/2✓ Branch 0 taken 186083274 times.
✗ Branch 1 not taken.
|
186083274 | update_row_stats(ROWS_READ); |
| 9661 | 186083274 | table->set_found_row(); | |
| 9662 | } | ||
| 9663 | |||
| 9664 | // skip_next is false when called from functions that are trying to iterate | ||
| 9665 | // through keys such as index_next/rnd_next/etc. and these functions | ||
| 9666 | // typically expect HA_ERR_END_OF_FILE if no next key is found. | ||
| 9667 |
2/2✓ Branch 0 taken 186325139 times.
✓ Branch 1 taken 6 times.
|
186325145 | if (!skip_next) { |
| 9668 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 186325139 times.
|
186325139 | if (rc == HA_ERR_KEY_NOT_FOUND) { |
| 9669 | ✗ | rc = HA_ERR_END_OF_FILE; | |
| 9670 | } | ||
| 9671 | } | ||
| 9672 | |||
| 9673 |
1/2✓ Branch 0 taken 186325145 times.
✗ Branch 1 not taken.
|
186325145 | DBUG_RETURN(rc); |
| 9674 | } | ||
| 9675 | |||
| 9676 | 24661501 | Rdb_iterator_base *ha_rocksdb::get_pk_iterator() { | |
| 9677 |
2/2✓ Branch 0 taken 3418291 times.
✓ Branch 1 taken 21274907 times.
|
24661501 | if (!m_pk_iterator) { |
| 9678 | 3418458 | m_pk_iterator.reset( | |
| 9679 |
2/4✓ Branch 0 taken 3418574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3418458 times.
✗ Branch 3 not taken.
|
3418291 | new Rdb_iterator_base(ha_thd(), m_pk_descr, m_pk_descr, m_tbl_def)); |
| 9680 | } | ||
| 9681 | 24693520 | return m_pk_iterator.get(); | |
| 9682 | } | ||
| 9683 | |||
| 9684 | /** | ||
| 9685 | @return | ||
| 9686 | HA_EXIT_SUCCESS OK | ||
| 9687 | other HA_ERR error code (can be SE-specific) | ||
| 9688 | */ | ||
| 9689 | 6811 | int ha_rocksdb::index_first(uchar *const buf) { | |
| 9690 |
1/2✓ Branch 0 taken 6811 times.
✗ Branch 1 not taken.
|
6811 | DBUG_ENTER_FUNC(); |
| 9691 | |||
| 9692 |
1/2✓ Branch 0 taken 6811 times.
✗ Branch 1 not taken.
|
6811 | check_build_decoder(); |
| 9693 | |||
| 9694 |
1/2✓ Branch 0 taken 6811 times.
✗ Branch 1 not taken.
|
6811 | ha_statistic_increment(&System_status_var::ha_read_first_count); |
| 9695 |
2/4✓ Branch 0 taken 6811 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6811 times.
✗ Branch 3 not taken.
|
13622 | DBUG_RETURN(index_read_intern(buf, true /* first */)); |
| 9696 | } | ||
| 9697 | |||
| 9698 | /** | ||
| 9699 | @return | ||
| 9700 | HA_EXIT_SUCCESS OK | ||
| 9701 | other HA_ERR error code (can be SE-specific) | ||
| 9702 | */ | ||
| 9703 | 2436 | int ha_rocksdb::index_last(uchar *const buf) { | |
| 9704 |
1/2✓ Branch 0 taken 2436 times.
✗ Branch 1 not taken.
|
2436 | DBUG_ENTER_FUNC(); |
| 9705 | |||
| 9706 |
1/2✓ Branch 0 taken 2436 times.
✗ Branch 1 not taken.
|
2436 | check_build_decoder(); |
| 9707 | |||
| 9708 |
1/2✓ Branch 0 taken 2436 times.
✗ Branch 1 not taken.
|
2436 | ha_statistic_increment(&System_status_var::ha_read_last_count); |
| 9709 |
2/4✓ Branch 0 taken 2436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2436 times.
✗ Branch 3 not taken.
|
4872 | DBUG_RETURN(index_read_intern(buf, false /* first */)); |
| 9710 | } | ||
| 9711 | |||
| 9712 | /* clang-format off */ | ||
| 9713 | /* | ||
| 9714 | index_read_intern is called by handler methods doing full table/index scans | ||
| 9715 | (eg. index_first/index_last). | ||
| 9716 | |||
| 9717 | 'first' refers to the logical seek direction in the table. | ||
| 9718 | |||
| 9719 | The implementation simply calls index_read_intern with nullptr as the key | ||
| 9720 | (which will default to using just the index id as the key) with either | ||
| 9721 | HA_READ_KEY_EXACT or HA_READ_PREFIX_LAST, for ascending and descending | ||
| 9722 | respectively. This will automatically give us the correct semantics as | ||
| 9723 | HA_READ_KEY_EXACT will return the first key with the given prefix, whereas | ||
| 9724 | HA_READ_PREFIX_LAST will return the last key with the given prefix. | ||
| 9725 | |||
| 9726 | At a lower level, there are four cases being handled in this function. | ||
| 9727 | |||
| 9728 | 1. Seeking to first row of table with forwards cf: | ||
| 9729 | |||
| 9730 | An picture of a forward-ordered keyspace (remember, the keys have form | ||
| 9731 | 'indexnr-keyval'. Suppose the index we are at has number n) | ||
| 9732 | |||
| 9733 | (n-1) - ... | ||
| 9734 | ( n ) <--- 1. (n) doesn't exist in the db but it would be here. | ||
| 9735 | ( n ) - aaa <--- 2. Seek("n") will put us here on the first index | ||
| 9736 | ( n ) - bbb record. | ||
| 9737 | ( n ) - cc | ||
| 9738 | |||
| 9739 | So, need to do: Seek(n); | ||
| 9740 | |||
| 9741 | 2. Seeking to last row of table with reverse cf: | ||
| 9742 | |||
| 9743 | (n+1) - bbb | ||
| 9744 | (n+1) - aaa | ||
| 9745 | (n+1) <--- (n+1) doesn't exist in the db but would be here. | ||
| 9746 | ( n ) - ccc <--- 1. We need to be here. | ||
| 9747 | ( n ) - bbb | ||
| 9748 | ( n ) - aaa | ||
| 9749 | ( n ) | ||
| 9750 | |||
| 9751 | So, need to: Seek(n+1); | ||
| 9752 | |||
| 9753 | 3. Seeking to last row of table with forwards cf: | ||
| 9754 | |||
| 9755 | An picture of a forward-ordered keyspace (remember, the keys have form | ||
| 9756 | 'indexnr-keyval'. Suppose the we are at a key that has number n) | ||
| 9757 | |||
| 9758 | (n-1)-something | ||
| 9759 | ( n )-aaa | ||
| 9760 | ( n )-bbb | ||
| 9761 | ( n )-ccc <----------- Need to seek to here. | ||
| 9762 | (n+1) <---- Doesn't exist, but would be here. | ||
| 9763 | (n+1)-smth, or no value at all | ||
| 9764 | |||
| 9765 | RocksDB's Iterator::SeekForPrev($val) seeks to "at $val or last value | ||
| 9766 | that's smaller". We can't seek to "(n)-ccc" directly, because we don't know | ||
| 9767 | what is the value of 'ccc' (the biggest record with prefix (n)). Instead, we | ||
| 9768 | seek to "(n+1)", which is the least possible value that's greater than any | ||
| 9769 | value in index #n. | ||
| 9770 | |||
| 9771 | So, need to: it->SeekForPrev(n+1) | ||
| 9772 | |||
| 9773 | 4. Seeking to first row of table with reverse cf: | ||
| 9774 | |||
| 9775 | (n+1)-something | ||
| 9776 | ( n ) - ccc | ||
| 9777 | ( n ) - bbb | ||
| 9778 | ( n ) - aaa <---------------- (*) Need to seek here. | ||
| 9779 | ( n ) <--- Doesn't exist, but would be here. | ||
| 9780 | (n-1)-smth, or no value at all | ||
| 9781 | |||
| 9782 | So, need to: it->SeekForPrev(n) | ||
| 9783 | */ | ||
| 9784 | /* clang-format on */ | ||
| 9785 | 32465 | int ha_rocksdb::index_read_intern(uchar *const buf, bool first) { | |
| 9786 |
1/2✓ Branch 0 taken 32465 times.
✗ Branch 1 not taken.
|
32465 | DBUG_ENTER_FUNC(); |
| 9787 |
3/4✓ Branch 0 taken 29906 times.
✓ Branch 1 taken 2559 times.
✓ Branch 2 taken 32465 times.
✗ Branch 3 not taken.
|
32465 | int rc = index_read_intern(buf, nullptr, 0, |
| 9788 | first ? HA_READ_KEY_EXACT : HA_READ_PREFIX_LAST); | ||
| 9789 | |||
| 9790 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32465 times.
|
32465 | if (rc == HA_ERR_KEY_NOT_FOUND) rc = HA_ERR_END_OF_FILE; |
| 9791 | |||
| 9792 |
1/2✓ Branch 0 taken 32465 times.
✗ Branch 1 not taken.
|
32465 | DBUG_RETURN(rc); |
| 9793 | } | ||
| 9794 | |||
| 9795 | 4174094 | void ha_rocksdb::unlock_row() { | |
| 9796 |
1/2✓ Branch 0 taken 4174094 times.
✗ Branch 1 not taken.
|
4174094 | DBUG_ENTER_FUNC(); |
| 9797 | |||
| 9798 |
2/2✓ Branch 0 taken 3606811 times.
✓ Branch 1 taken 567283 times.
|
4174094 | if (m_lock_rows != RDB_LOCK_NONE) { |
| 9799 |
1/2✓ Branch 0 taken 3606811 times.
✗ Branch 1 not taken.
|
3606811 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); |
| 9800 |
1/2✓ Branch 0 taken 3606811 times.
✗ Branch 1 not taken.
|
3606811 | tx->release_lock(*m_pk_descr, |
| 9801 |
1/2✓ Branch 0 taken 3606811 times.
✗ Branch 1 not taken.
|
7213622 | std::string(m_last_rowkey.ptr(), m_last_rowkey.length())); |
| 9802 | } | ||
| 9803 | |||
| 9804 |
1/2✓ Branch 0 taken 4174094 times.
✗ Branch 1 not taken.
|
8348188 | DBUG_VOID_RETURN; |
| 9805 | } | ||
| 9806 | |||
| 9807 | /* | ||
| 9808 | Returning true if SingleDelete can be used. | ||
| 9809 | - Secondary Indexes can always use SingleDelete. | ||
| 9810 | - If the index is PRIMARY KEY, and if all of the columns of the table | ||
| 9811 | are covered by the PRIMARY KEY, SingleDelete can be used. | ||
| 9812 | */ | ||
| 9813 | 488615 | bool ha_rocksdb::can_use_single_delete(const uint index) const { | |
| 9814 |
1/2✓ Branch 0 taken 488615 times.
✗ Branch 1 not taken.
|
977230 | return (index != pk_index(table, m_tbl_def) || |
| 9815 |
2/2✓ Branch 0 taken 483454 times.
✓ Branch 1 taken 5161 times.
|
488615 | (!has_hidden_pk(table) && |
| 9816 |
2/2✓ Branch 0 taken 104378 times.
✓ Branch 1 taken 379076 times.
|
972069 | table->key_info[index].actual_key_parts == table->s->fields)); |
| 9817 | } | ||
| 9818 | |||
| 9819 | 74662174 | bool ha_rocksdb::skip_unique_check() const { | |
| 9820 | /* | ||
| 9821 | We want to skip unique checks if: | ||
| 9822 | 1) bulk_load is on | ||
| 9823 | 2) the user set unique_checks option to 0, and the table does not have | ||
| 9824 | any indexes. If the table has secondary keys, then those might becomes | ||
| 9825 | inconsisted/corrupted | ||
| 9826 | 3) We're using read-free replication | ||
| 9827 | */ | ||
| 9828 | 74662174 | return THDVAR(table->in_use, bulk_load) || | |
| 9829 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 12077770 times.
|
12104281 | (my_core::thd_test_options(table->in_use, |
| 9830 | 186 | OPTION_RELAXED_UNIQUE_CHECKS) && | |
| 9831 |
3/4✓ Branch 0 taken 12104281 times.
✓ Branch 1 taken 62565435 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4975 times.
|
86837681 | m_tbl_def->m_key_count == 1) || |
| 9832 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12169885 times.
|
86811170 | use_read_free_rpl(); |
| 9833 | } | ||
| 9834 | |||
| 9835 | 71197875 | bool commit_in_the_middle(THD *thd) { | |
| 9836 | // It does not make sense to use write unprepared with commit in the middle, | ||
| 9837 | // since both handle large transactions by flushing the write batches onto | ||
| 9838 | // disk. | ||
| 9839 | // | ||
| 9840 | // For the two to work together, we would need to assign a new xid after | ||
| 9841 | // committing. | ||
| 9842 |
4/4✓ Branch 0 taken 9061526 times.
✓ Branch 1 taken 62156989 times.
✓ Branch 2 taken 37222 times.
✓ Branch 3 taken 9056532 times.
|
133392086 | return (THDVAR(thd, bulk_load) || THDVAR(thd, commit_in_the_middle)) && |
| 9843 |
2/2✓ Branch 0 taken 42492833 times.
✓ Branch 1 taken 19701378 times.
|
133444954 | rocksdb_write_policy != rocksdb::TxnDBWritePolicy::WRITE_UNPREPARED; |
| 9844 | } | ||
| 9845 | |||
| 9846 | /* | ||
| 9847 | Executing bulk commit if it should. | ||
| 9848 | @retval true if bulk commit failed | ||
| 9849 | @retval false if bulk commit was skipped or succeeded | ||
| 9850 | */ | ||
| 9851 | 70939922 | bool ha_rocksdb::do_bulk_commit(Rdb_transaction *const tx) { | |
| 9852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70939922 times.
|
70939922 | assert(tx != nullptr); |
| 9853 | 70939922 | return commit_in_the_middle(table->in_use) && | |
| 9854 |
4/4✓ Branch 0 taken 42492695 times.
✓ Branch 1 taken 28495659 times.
✓ Branch 2 taken 478 times.
✓ Branch 3 taken 42462121 times.
|
70988832 | tx->get_write_count() >= THDVAR(table->in_use, bulk_load_size) && |
| 9855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 478 times.
|
70958736 | tx->flush_batch(); |
| 9856 | } | ||
| 9857 | |||
| 9858 | /* | ||
| 9859 | If table was created without primary key, SQL layer represents the primary | ||
| 9860 | key number as MAX_INDEXES. Hence, this function returns true if the table | ||
| 9861 | does not contain a primary key. (In which case we generate a hidden | ||
| 9862 | 'auto-incremented' pk.) | ||
| 9863 | */ | ||
| 9864 | 72753233 | bool ha_rocksdb::has_hidden_pk(const TABLE *const table) const { | |
| 9865 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 72753233 times.
|
72753233 | assert(table != nullptr); |
| 9866 | 72753233 | return Rdb_key_def::table_has_hidden_pk(table); | |
| 9867 | } | ||
| 9868 | |||
| 9869 | /* | ||
| 9870 | Returns true if given index number is a hidden_pk. | ||
| 9871 | - This is used when a table is created with no primary key. | ||
| 9872 | */ | ||
| 9873 | 138127568 | bool ha_rocksdb::is_hidden_pk(const uint index, const TABLE *const table_arg, | |
| 9874 | const Rdb_tbl_def *const tbl_def_arg) { | ||
| 9875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 138127568 times.
|
138127568 | assert(table_arg != nullptr); |
| 9876 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 138127568 times.
|
138127568 | assert(table_arg->s != nullptr); |
| 9877 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 138127568 times.
|
138127568 | assert(tbl_def_arg != nullptr); |
| 9878 | |||
| 9879 |
2/2✓ Branch 0 taken 7149842 times.
✓ Branch 1 taken 130977726 times.
|
145277410 | return (table_arg->s->primary_key == MAX_INDEXES && |
| 9880 |
2/2✓ Branch 0 taken 1320253 times.
✓ Branch 1 taken 5829589 times.
|
145277410 | index == tbl_def_arg->m_key_count - 1); |
| 9881 | } | ||
| 9882 | |||
| 9883 | /* Returns index of primary key */ | ||
| 9884 | 906995 | uint ha_rocksdb::pk_index(const TABLE *const table_arg, | |
| 9885 | const Rdb_tbl_def *const tbl_def_arg) { | ||
| 9886 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 906995 times.
|
906995 | assert(table_arg != nullptr); |
| 9887 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 906995 times.
|
906995 | assert(table_arg->s != nullptr); |
| 9888 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 906995 times.
|
906995 | assert(tbl_def_arg != nullptr); |
| 9889 | |||
| 9890 |
2/2✓ Branch 0 taken 33315 times.
✓ Branch 1 taken 873680 times.
|
906995 | return table_arg->s->primary_key == MAX_INDEXES ? tbl_def_arg->m_key_count - 1 |
| 9891 | 906995 | : table_arg->s->primary_key; | |
| 9892 | } | ||
| 9893 | |||
| 9894 | /* Returns the index into m_key_descr_arr array based on active_index */ | ||
| 9895 | 284316166 | uint ha_rocksdb::active_index_pos() { | |
| 9896 |
2/2✓ Branch 0 taken 652015 times.
✓ Branch 1 taken 283664151 times.
|
284316166 | return active_index == MAX_KEY ? m_tbl_def->m_key_count - 1 : active_index; |
| 9897 | } | ||
| 9898 | |||
| 9899 | /* Returns true if given index number is a primary key */ | ||
| 9900 | 145214052 | bool ha_rocksdb::is_pk(const uint index, const TABLE *const table_arg, | |
| 9901 | const Rdb_tbl_def *const tbl_def_arg) { | ||
| 9902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 145214052 times.
|
145214052 | assert(table_arg != nullptr); |
| 9903 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 145214052 times.
|
145214052 | assert(table_arg->s != nullptr); |
| 9904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 145214052 times.
|
145214052 | assert(tbl_def_arg != nullptr); |
| 9905 | |||
| 9906 |
2/2✓ Branch 0 taken 66617158 times.
✓ Branch 1 taken 78596894 times.
|
211831210 | return index == table_arg->s->primary_key || |
| 9907 |
2/2✓ Branch 0 taken 847516 times.
✓ Branch 1 taken 65769642 times.
|
211831210 | is_hidden_pk(index, table_arg, tbl_def_arg); |
| 9908 | } | ||
| 9909 | |||
| 9910 | 18432 | uint ha_rocksdb::max_supported_key_part_length( | |
| 9911 | HA_CREATE_INFO *create_info MY_ATTRIBUTE((__unused__))) const { | ||
| 9912 |
1/2✓ Branch 0 taken 18432 times.
✗ Branch 1 not taken.
|
18432 | DBUG_ENTER_FUNC(); |
| 9913 |
3/4✓ Branch 0 taken 18432 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18384 times.
✓ Branch 3 taken 48 times.
|
18432 | DBUG_RETURN(rocksdb_large_prefix ? MAX_INDEX_COL_LEN_LARGE |
| 9914 | : MAX_INDEX_COL_LEN_SMALL); | ||
| 9915 | } | ||
| 9916 | |||
| 9917 | 29952 | const char *ha_rocksdb::get_key_name(const uint index, | |
| 9918 | const TABLE *const table_arg, | ||
| 9919 | const Rdb_tbl_def *const tbl_def_arg) { | ||
| 9920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29952 times.
|
29952 | assert(table_arg != nullptr); |
| 9921 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29952 times.
|
29952 | assert(tbl_def_arg != nullptr); |
| 9922 | |||
| 9923 |
2/2✓ Branch 0 taken 6460 times.
✓ Branch 1 taken 23492 times.
|
29952 | if (is_hidden_pk(index, table_arg, tbl_def_arg)) { |
| 9924 | 6460 | return HIDDEN_PK_NAME; | |
| 9925 | } | ||
| 9926 | |||
| 9927 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23492 times.
|
23492 | assert(table_arg->key_info != nullptr); |
| 9928 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23492 times.
|
23492 | assert(table_arg->key_info[index].name != nullptr); |
| 9929 | |||
| 9930 | 23492 | return table_arg->key_info[index].name; | |
| 9931 | } | ||
| 9932 | |||
| 9933 | 28329 | const char *ha_rocksdb::get_key_comment(const uint index, | |
| 9934 | const TABLE *const table_arg, | ||
| 9935 | const Rdb_tbl_def *const tbl_def_arg) { | ||
| 9936 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28329 times.
|
28329 | assert(table_arg != nullptr); |
| 9937 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28329 times.
|
28329 | assert(tbl_def_arg != nullptr); |
| 9938 | |||
| 9939 |
2/2✓ Branch 0 taken 6142 times.
✓ Branch 1 taken 22187 times.
|
28329 | if (is_hidden_pk(index, table_arg, tbl_def_arg)) { |
| 9940 | 6142 | return nullptr; | |
| 9941 | } | ||
| 9942 | |||
| 9943 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22187 times.
|
22187 | assert(table_arg->key_info != nullptr); |
| 9944 | |||
| 9945 | 22187 | return table_arg->key_info[index].comment.str; | |
| 9946 | } | ||
| 9947 | |||
| 9948 | 28329 | const std::string ha_rocksdb::generate_cf_name( | |
| 9949 | const uint index, const TABLE *const table_arg, | ||
| 9950 | const Rdb_tbl_def *const tbl_def_arg, bool *per_part_match_found) { | ||
| 9951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28329 times.
|
28329 | assert(table_arg != nullptr); |
| 9952 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28329 times.
|
28329 | assert(tbl_def_arg != nullptr); |
| 9953 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28329 times.
|
28329 | assert(per_part_match_found != nullptr); |
| 9954 | |||
| 9955 | // When creating CF-s the caller needs to know if there was a custom CF name | ||
| 9956 | // specified for a given paritition. | ||
| 9957 | 28329 | *per_part_match_found = false; | |
| 9958 | |||
| 9959 | // Index comment is used to define the column family name specification(s). | ||
| 9960 | // If there was no comment, we get an emptry string, and it means "use the | ||
| 9961 | // default column family". | ||
| 9962 |
1/2✓ Branch 0 taken 28329 times.
✗ Branch 1 not taken.
|
28329 | const char *const comment = get_key_comment(index, table_arg, tbl_def_arg); |
| 9963 | |||
| 9964 | // `get_key_comment` can return `nullptr`, that's why this. | ||
| 9965 |
3/4✓ Branch 0 taken 2200 times.
✓ Branch 1 taken 26129 times.
✓ Branch 2 taken 28329 times.
✗ Branch 3 not taken.
|
28329 | std::string key_comment = comment ? comment : ""; |
| 9966 | |||
| 9967 | std::string cf_name = Rdb_key_def::parse_comment_for_qualifier( | ||
| 9968 | key_comment, table_arg, tbl_def_arg, per_part_match_found, | ||
| 9969 |
1/2✓ Branch 0 taken 28329 times.
✗ Branch 1 not taken.
|
28329 | RDB_CF_NAME_QUALIFIER); |
| 9970 | |||
| 9971 |
4/4✓ Branch 0 taken 12092 times.
✓ Branch 1 taken 16237 times.
✓ Branch 2 taken 11627 times.
✓ Branch 3 taken 465 times.
|
28329 | if (table_arg->part_info != nullptr && !*per_part_match_found) { |
| 9972 | // At this point we tried to search for a custom CF name for a partition, | ||
| 9973 | // but none was specified. Therefore default one will be used. | ||
| 9974 |
1/2✓ Branch 0 taken 11627 times.
✗ Branch 1 not taken.
|
11627 | return ""; |
| 9975 | } | ||
| 9976 | |||
| 9977 | // If we didn't find any partitioned/non-partitioned qualifiers, DO NOT return | ||
| 9978 | // the comment itself. FB 5.6 Behavior is exactly the opposite which then | ||
| 9979 | // causes any index comment to create a new column family. | ||
| 9980 | |||
| 9981 | // Strip leading and trailing whitespace as that is not part of a valid name | ||
| 9982 |
3/4✓ Branch 0 taken 1563 times.
✓ Branch 1 taken 15139 times.
✓ Branch 2 taken 1563 times.
✗ Branch 3 not taken.
|
16702 | if (!cf_name.empty()) rdb_trim_whitespace_from_edges(cf_name); |
| 9983 | |||
| 9984 | 16702 | return cf_name; | |
| 9985 | 28329 | } | |
| 9986 | |||
| 9987 | ✗ | const std::string ha_rocksdb::get_table_comment(const TABLE *const table_arg) { | |
| 9988 | ✗ | assert(table_arg != nullptr); | |
| 9989 | ✗ | assert(table_arg->s != nullptr); | |
| 9990 | |||
| 9991 | ✗ | return table_arg->s->comment.str; | |
| 9992 | } | ||
| 9993 | |||
| 9994 | /** | ||
| 9995 | Write a new row | ||
| 9996 | |||
| 9997 | @param[in] buf new row data to write | ||
| 9998 | @return | ||
| 9999 | HA_EXIT_SUCCESS OK | ||
| 10000 | other HA_ERR error code (can be SE-specific) | ||
| 10001 | */ | ||
| 10002 | 70405715 | int ha_rocksdb::write_row(uchar *const buf) { | |
| 10003 |
1/2✓ Branch 0 taken 70485150 times.
✗ Branch 1 not taken.
|
70405715 | DBUG_ENTER_FUNC(); |
| 10004 | |||
| 10005 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70485150 times.
|
70485150 | assert(buf != nullptr); |
| 10006 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70485150 times.
|
70485150 | assert(buf == table->record[0]); |
| 10007 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70485150 times.
|
70485150 | assert(m_lock_rows == RDB_LOCK_WRITE); |
| 10008 | |||
| 10009 |
1/2✓ Branch 0 taken 70479870 times.
✗ Branch 1 not taken.
|
70485150 | ha_statistic_increment(&System_status_var::ha_write_count); |
| 10010 | /* | ||
| 10011 | Note: "buf == table->record[0]" is copied from innodb. I am not aware of | ||
| 10012 | any use cases where this condition is not true. | ||
| 10013 | */ | ||
| 10014 |
3/4✓ Branch 0 taken 8227499 times.
✓ Branch 1 taken 62252371 times.
✓ Branch 2 taken 8227968 times.
✗ Branch 3 not taken.
|
70479870 | if (table->next_number_field && buf == table->record[0]) { |
| 10015 | int err; | ||
| 10016 |
3/4✓ Branch 0 taken 8242985 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 8242961 times.
|
8227968 | if ((err = update_auto_increment())) { |
| 10017 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | DBUG_RETURN(err); |
| 10018 | } | ||
| 10019 | } | ||
| 10020 | |||
| 10021 | // clear cache at beginning of write for INSERT ON DUPLICATE | ||
| 10022 | // we may get multiple write->fail->read->update if there are multiple | ||
| 10023 | // values from INSERT | ||
| 10024 | 70494863 | m_dup_key_found = false; | |
| 10025 | |||
| 10026 |
2/4✓ Branch 0 taken 70485266 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70442760 times.
✗ Branch 3 not taken.
|
70494863 | const int rv = update_write_row(nullptr, buf, skip_unique_check()); |
| 10027 | |||
| 10028 |
1/2✓ Branch 0 taken 70447288 times.
✗ Branch 1 not taken.
|
70442760 | if (rv == 0) { |
| 10029 | // Not protected by ddl_manger lock for performance | ||
| 10030 | // reasons. This is an estimate value anyway. | ||
| 10031 |
1/2✓ Branch 0 taken 70447947 times.
✗ Branch 1 not taken.
|
70447288 | inc_table_n_rows(); |
| 10032 |
1/2✓ Branch 0 taken 70484614 times.
✗ Branch 1 not taken.
|
70447947 | update_table_stats_if_needed(); |
| 10033 | |||
| 10034 |
1/2✓ Branch 0 taken 70479274 times.
✗ Branch 1 not taken.
|
70484614 | update_row_stats(ROWS_INSERTED); |
| 10035 | } | ||
| 10036 | |||
| 10037 |
1/2✓ Branch 0 taken 70494382 times.
✗ Branch 1 not taken.
|
70474746 | DBUG_RETURN(rv); |
| 10038 | } | ||
| 10039 | |||
| 10040 | // Increment the number of rows in the table by one. | ||
| 10041 | // This operation is not protected by ddl manager lock. | ||
| 10042 | // The number is estimated. | ||
| 10043 | 70443055 | void ha_rocksdb::inc_table_n_rows() { | |
| 10044 |
2/2✓ Branch 0 taken 70416937 times.
✓ Branch 1 taken 26118 times.
|
70443055 | if (!rocksdb_table_stats_use_table_scan) { |
| 10045 | 70416937 | return; | |
| 10046 | } | ||
| 10047 | |||
| 10048 | 26118 | uint64 n_rows = m_tbl_def->m_tbl_stats.m_stat_n_rows; | |
| 10049 |
1/2✓ Branch 0 taken 30372 times.
✗ Branch 1 not taken.
|
26118 | if (n_rows < std::numeric_limits<ulonglong>::max()) { |
| 10050 | 30372 | m_tbl_def->m_tbl_stats.m_stat_n_rows = n_rows + 1; | |
| 10051 | } | ||
| 10052 | } | ||
| 10053 | |||
| 10054 | // Decrement the number of rows in the table by one. | ||
| 10055 | // This operation is not protected by ddl manager lock. | ||
| 10056 | // The number is estimated. | ||
| 10057 | 240972 | void ha_rocksdb::dec_table_n_rows() { | |
| 10058 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | if (!rocksdb_table_stats_use_table_scan) { |
| 10059 | 240972 | return; | |
| 10060 | } | ||
| 10061 | |||
| 10062 | ✗ | uint64 n_rows = m_tbl_def->m_tbl_stats.m_stat_n_rows; | |
| 10063 | ✗ | if (n_rows > 0) { | |
| 10064 | ✗ | m_tbl_def->m_tbl_stats.m_stat_n_rows = n_rows - 1; | |
| 10065 | } | ||
| 10066 | } | ||
| 10067 | |||
| 10068 | /** | ||
| 10069 | Constructing m_last_rowkey (MyRocks key expression) from | ||
| 10070 | before_update|delete image (MySQL row expression). | ||
| 10071 | m_last_rowkey is normally set during lookup phase, such as | ||
| 10072 | rnd_next() and rnd_pos(). With Read Free Replication, | ||
| 10073 | these read functions are skipped and update_rows(), delete_rows() are | ||
| 10074 | called without setting m_last_rowkey. This function sets m_last_rowkey | ||
| 10075 | for Read Free Replication. | ||
| 10076 | */ | ||
| 10077 | 70884292 | void ha_rocksdb::set_last_rowkey(const uchar *const old_data) { | |
| 10078 | #if defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 10079 |
4/6✓ Branch 0 taken 506699 times.
✓ Branch 1 taken 70377593 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 506699 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 70884292 times.
|
70884292 | if (old_data && use_read_free_rpl()) { |
| 10080 | ✗ | const int old_pk_size = m_pk_descr->pack_record( | |
| 10081 | ✗ | table, m_pack_buffer, old_data, m_pk_packed_tuple, nullptr, false); | |
| 10082 | ✗ | m_last_rowkey.copy((const char *)m_pk_packed_tuple, old_pk_size, | |
| 10083 | &my_charset_bin); | ||
| 10084 | } | ||
| 10085 | #endif // defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 10086 | 70884292 | } | |
| 10087 | |||
| 10088 | ✗ | void ha_rocksdb::set_last_rowkey(const char *str, size_t len) { | |
| 10089 | ✗ | m_last_rowkey.copy(str, len, &my_charset_bin); | |
| 10090 | } | ||
| 10091 | |||
| 10092 | /** | ||
| 10093 | Collect update data for primary key | ||
| 10094 | |||
| 10095 | @param[in, out] row_info hold all data for update row, such as | ||
| 10096 | new row data/old row data | ||
| 10097 | @return | ||
| 10098 | HA_EXIT_SUCCESS OK | ||
| 10099 | other HA_ERR error code (can be SE-specific) | ||
| 10100 | */ | ||
| 10101 | 70633387 | int ha_rocksdb::get_pk_for_update(struct update_row_info *const row_info) { | |
| 10102 | int size; | ||
| 10103 | |||
| 10104 | /* | ||
| 10105 | Get new row key for any insert, and any update where the pk is not hidden. | ||
| 10106 | Row key for updates with hidden pk is handled below. | ||
| 10107 | */ | ||
| 10108 |
2/2✓ Branch 0 taken 70220505 times.
✓ Branch 1 taken 418971 times.
|
70633387 | if (!has_hidden_pk(table)) { |
| 10109 | 70220505 | row_info->hidden_pk_id = 0; | |
| 10110 | |||
| 10111 | 70220505 | row_info->new_pk_unpack_info = &m_pk_unpack_info; | |
| 10112 | |||
| 10113 | 140537348 | size = m_pk_descr->pack_record( | |
| 10114 | 70223812 | table, m_pack_buffer, row_info->new_data, m_pk_packed_tuple, | |
| 10115 | row_info->new_pk_unpack_info, false, 0, 0, nullptr); | ||
| 10116 |
2/2✓ Branch 0 taken 400949 times.
✓ Branch 1 taken 18022 times.
|
418971 | } else if (row_info->old_data == nullptr) { |
| 10117 | 400949 | row_info->hidden_pk_id = update_hidden_pk_val(); | |
| 10118 | 400949 | size = | |
| 10119 | 400949 | m_pk_descr->pack_hidden_pk(row_info->hidden_pk_id, m_pk_packed_tuple); | |
| 10120 | } else { | ||
| 10121 | /* | ||
| 10122 | If hidden primary key, rowkey for new record will always be the same as | ||
| 10123 | before | ||
| 10124 | */ | ||
| 10125 | 18022 | size = row_info->old_pk_slice.size(); | |
| 10126 | 18022 | memcpy(m_pk_packed_tuple, row_info->old_pk_slice.data(), size); | |
| 10127 | 18022 | int err = read_hidden_pk_id_from_rowkey(&row_info->hidden_pk_id); | |
| 10128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18022 times.
|
18022 | if (err) { |
| 10129 | ✗ | return err; | |
| 10130 | } | ||
| 10131 | } | ||
| 10132 | |||
| 10133 | 70628798 | row_info->new_pk_slice = | |
| 10134 | 70735814 | rocksdb::Slice((const char *)m_pk_packed_tuple, size); | |
| 10135 | |||
| 10136 | 70628798 | return HA_EXIT_SUCCESS; | |
| 10137 | } | ||
| 10138 | |||
| 10139 | /** | ||
| 10140 | Check the specified primary key value is unique and also lock the row | ||
| 10141 | |||
| 10142 | @param[in] row_info hold all data for update row, such as old row | ||
| 10143 | data and new row data | ||
| 10144 | @param[out] found whether the primary key exists before. | ||
| 10145 | @param[out] pk_changed whether primary key is changed | ||
| 10146 | @return | ||
| 10147 | HA_EXIT_SUCCESS OK | ||
| 10148 | other HA_ERR error code (can be SE-specific) | ||
| 10149 | */ | ||
| 10150 | 8353626 | int ha_rocksdb::check_and_lock_unique_pk(const struct update_row_info &row_info, | |
| 10151 | bool *const found, | ||
| 10152 | const bool skip_unique_check) { | ||
| 10153 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8353626 times.
|
8353626 | assert(found != nullptr); |
| 10154 | |||
| 10155 |
4/6✓ Branch 0 taken 143472 times.
✓ Branch 1 taken 8216714 times.
✓ Branch 2 taken 143472 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 143472 times.
|
8353626 | assert(row_info.old_pk_slice.size() == 0 || |
| 10156 | row_info.new_pk_slice.compare(row_info.old_pk_slice) != 0); | ||
| 10157 | |||
| 10158 | 8360186 | const bool ignore_pk_unique_check = skip_unique_check; | |
| 10159 |
1/2✓ Branch 0 taken 8385765 times.
✗ Branch 1 not taken.
|
8360186 | rocksdb::PinnableSlice value; |
| 10160 | 8385765 | rocksdb::PinnableSlice *pslice = | |
| 10161 |
2/2✓ Branch 0 taken 585 times.
✓ Branch 1 taken 8385180 times.
|
8385765 | m_insert_with_update ? &m_dup_key_retrieved_record : &value; |
| 10162 | |||
| 10163 | /* | ||
| 10164 | Perform a read to determine if a duplicate entry exists. For primary | ||
| 10165 | keys, a point lookup will be sufficient. | ||
| 10166 | |||
| 10167 | note: we intentionally don't set options.snapshot here. We want to read | ||
| 10168 | the latest committed data. | ||
| 10169 | */ | ||
| 10170 | |||
| 10171 | /* | ||
| 10172 | To prevent race conditions like below, it is necessary to | ||
| 10173 | take a lock for a target row. get_for_update() holds a gap lock if | ||
| 10174 | target key does not exist, so below conditions should never | ||
| 10175 | happen. | ||
| 10176 | |||
| 10177 | 1) T1 Get(empty) -> T2 Get(empty) -> T1 Put(insert) -> T1 commit | ||
| 10178 | -> T2 Put(overwrite) -> T2 commit | ||
| 10179 | 2) T1 Get(empty) -> T1 Put(insert, not committed yet) -> T2 Get(empty) | ||
| 10180 | -> T2 Put(insert, blocked) -> T1 commit -> T2 commit(overwrite) | ||
| 10181 | */ | ||
| 10182 |
4/6✓ Branch 0 taken 8403395 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 8403299 times.
✓ Branch 4 taken 8400781 times.
✗ Branch 5 not taken.
|
8385765 | int rc = get_pk_iterator()->get(&row_info.new_pk_slice, |
| 10183 | ignore_pk_unique_check ? nullptr : pslice, | ||
| 10184 | m_lock_rows); | ||
| 10185 | |||
| 10186 |
3/4✓ Branch 0 taken 8415369 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 8415311 times.
|
8400781 | if (rc && rc != HA_ERR_KEY_NOT_FOUND) { |
| 10187 | 58 | return rc; | |
| 10188 | } | ||
| 10189 | |||
| 10190 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 8400627 times.
|
8400723 | bool key_found = ignore_pk_unique_check ? false : (rc == HA_EXIT_SUCCESS); |
| 10191 | |||
| 10192 |
6/6✓ Branch 0 taken 2462 times.
✓ Branch 1 taken 8398261 times.
✓ Branch 2 taken 2451 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 161 times.
✓ Branch 5 taken 2290 times.
|
8400723 | if (key_found && row_info.old_data == nullptr && m_insert_with_update) { |
| 10193 | // In INSERT ON DUPLICATE KEY UPDATE ... case, if the insert failed | ||
| 10194 | // due to a duplicate key, remember the last key and skip the check | ||
| 10195 | // next time | ||
| 10196 | 161 | m_dup_key_found = true; | |
| 10197 | #ifndef NDEBUG | ||
| 10198 | // save it for sanity checking later | ||
| 10199 |
1/2✓ Branch 0 taken 17060 times.
✗ Branch 1 not taken.
|
161 | m_dup_key_tuple.copy(row_info.new_pk_slice.data(), |
| 10200 | row_info.new_pk_slice.size(), &my_charset_bin); | ||
| 10201 | #endif | ||
| 10202 | } | ||
| 10203 | |||
| 10204 | 8417622 | *found = key_found; | |
| 10205 | |||
| 10206 | 8417622 | return HA_EXIT_SUCCESS; | |
| 10207 | 8417680 | } | |
| 10208 | |||
| 10209 | 18270 | int ha_rocksdb::acquire_prefix_lock(const Rdb_key_def &kd, Rdb_transaction *tx, | |
| 10210 | const uchar *data) { | ||
| 10211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18270 times.
|
18270 | assert(kd.is_partial_index()); |
| 10212 | // Obtain shared lock on prefix. | ||
| 10213 |
1/2✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
|
18270 | uint size = kd.pack_record(table, m_pack_buffer, data, m_sk_packed_tuple, |
| 10214 | nullptr, false, 0, kd.partial_index_keyparts()); | ||
| 10215 | const rocksdb::Slice prefix_slice = | ||
| 10216 | 18270 | rocksdb::Slice((const char *)m_sk_packed_tuple, size); | |
| 10217 | |||
| 10218 | const rocksdb::Status s = | ||
| 10219 | 18270 | tx->get_for_update(kd, prefix_slice, nullptr, false /* exclusive */, | |
| 10220 |
1/2✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
|
18270 | false /* do validate */, false /* no_wait */); |
| 10221 |
2/4✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18270 times.
|
18270 | if (!s.ok()) { |
| 10222 | ✗ | return tx->set_status_error(table->in_use, s, kd, m_tbl_def); | |
| 10223 | } | ||
| 10224 | |||
| 10225 | 18270 | return HA_EXIT_SUCCESS; | |
| 10226 | 18270 | } | |
| 10227 | |||
| 10228 | /** | ||
| 10229 | Check the specified secondary key value is unique and also lock the row | ||
| 10230 | |||
| 10231 | @param[in] key_id key index | ||
| 10232 | @param[in] row_info hold all data for update row, such as old row | ||
| 10233 | data and new row data | ||
| 10234 | @param[out] found whether specified key value exists before. | ||
| 10235 | @return | ||
| 10236 | HA_EXIT_SUCCESS OK | ||
| 10237 | other HA_ERR error code (can be SE-specific) | ||
| 10238 | */ | ||
| 10239 | 12503856 | int ha_rocksdb::check_and_lock_sk( | |
| 10240 | const uint key_id, const struct update_row_info &row_info, | ||
| 10241 | bool *const found, | ||
| 10242 | const bool skip_unique_check MY_ATTRIBUTE((__unused__))) { | ||
| 10243 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12503856 times.
|
12503856 | assert(found != nullptr); |
| 10244 | 12503856 | *found = false; | |
| 10245 | |||
| 10246 | /* | ||
| 10247 | Can skip checking this key if none of the key fields have changed. | ||
| 10248 | */ | ||
| 10249 |
6/6✓ Branch 0 taken 287054 times.
✓ Branch 1 taken 12216802 times.
✓ Branch 2 taken 600 times.
✓ Branch 3 taken 286454 times.
✓ Branch 4 taken 600 times.
✓ Branch 5 taken 12503256 times.
|
12503856 | if (row_info.old_data != nullptr && !m_update_scope.is_set(key_id)) { |
| 10250 | 600 | return HA_EXIT_SUCCESS; | |
| 10251 | } | ||
| 10252 | |||
| 10253 | 12503256 | KEY *key_info = nullptr; | |
| 10254 | 12503256 | uint n_null_fields = 0; | |
| 10255 | 12503256 | uint user_defined_key_parts = 1; | |
| 10256 | 12503256 | int rc = HA_EXIT_SUCCESS; | |
| 10257 | |||
| 10258 | 12503256 | key_info = &table->key_info[key_id]; | |
| 10259 | 12503256 | user_defined_key_parts = key_info->user_defined_key_parts; | |
| 10260 | 12503256 | const Rdb_key_def &kd = *m_key_descr_arr[key_id]; | |
| 10261 | |||
| 10262 |
2/2✓ Branch 0 taken 18270 times.
✓ Branch 1 taken 12484986 times.
|
12503256 | if (kd.is_partial_index()) { |
| 10263 | // Obtain shared lock on new/old prefix. | ||
| 10264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18270 times.
|
18270 | if (row_info.old_data != nullptr) { |
| 10265 | ✗ | rc = acquire_prefix_lock(kd, row_info.tx, row_info.old_data); | |
| 10266 | ✗ | if (rc) return rc; | |
| 10267 | } | ||
| 10268 | |||
| 10269 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18270 times.
|
18270 | assert(row_info.new_data != nullptr); |
| 10270 |
1/2✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
|
18270 | rc = acquire_prefix_lock(kd, row_info.tx, row_info.new_data); |
| 10271 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18270 times.
|
18270 | if (rc) return rc; |
| 10272 | } | ||
| 10273 | |||
| 10274 | /* | ||
| 10275 | If there are no uniqueness requirements, there's no need to obtain a | ||
| 10276 | lock for this key. | ||
| 10277 | */ | ||
| 10278 |
2/2✓ Branch 0 taken 12490598 times.
✓ Branch 1 taken 12658 times.
|
12503256 | if (!(key_info->flags & HA_NOSAME)) { |
| 10279 | 12490598 | return HA_EXIT_SUCCESS; | |
| 10280 | } | ||
| 10281 | |||
| 10282 | /* | ||
| 10283 | Calculate the new key for obtaining the lock | ||
| 10284 | |||
| 10285 | For unique secondary indexes, the key used for locking does not | ||
| 10286 | include the extended fields. | ||
| 10287 | */ | ||
| 10288 | int size = | ||
| 10289 |
1/2✓ Branch 0 taken 12658 times.
✗ Branch 1 not taken.
|
12658 | kd.pack_record(table, m_pack_buffer, row_info.new_data, m_sk_packed_tuple, |
| 10290 | 12658 | nullptr, false, 0, user_defined_key_parts, &n_null_fields); | |
| 10291 |
2/2✓ Branch 0 taken 144 times.
✓ Branch 1 taken 12514 times.
|
12658 | if (n_null_fields > 0) { |
| 10292 | /* | ||
| 10293 | If any fields are marked as NULL this will never match another row as | ||
| 10294 | to NULL never matches anything else including another NULL. | ||
| 10295 | */ | ||
| 10296 | 144 | return HA_EXIT_SUCCESS; | |
| 10297 | } | ||
| 10298 | |||
| 10299 | const rocksdb::Slice new_slice = | ||
| 10300 | 12514 | rocksdb::Slice((const char *)m_sk_packed_tuple, size); | |
| 10301 | |||
| 10302 | /* | ||
| 10303 | Acquire lock on the old key in case of UPDATE | ||
| 10304 | */ | ||
| 10305 |
2/2✓ Branch 0 taken 2772 times.
✓ Branch 1 taken 9742 times.
|
12514 | if (row_info.old_data != nullptr) { |
| 10306 |
1/2✓ Branch 0 taken 2772 times.
✗ Branch 1 not taken.
|
2772 | size = kd.pack_record(table, m_pack_buffer, row_info.old_data, |
| 10307 | m_sk_packed_tuple_old, nullptr, false, 0, | ||
| 10308 | user_defined_key_parts); | ||
| 10309 | const rocksdb::Slice old_slice = | ||
| 10310 | 2772 | rocksdb::Slice((const char *)m_sk_packed_tuple_old, size); | |
| 10311 | |||
| 10312 |
1/2✓ Branch 0 taken 2772 times.
✗ Branch 1 not taken.
|
2772 | const rocksdb::Status s = get_for_update(row_info.tx, kd, old_slice); |
| 10313 |
2/4✓ Branch 0 taken 2772 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2772 times.
|
2772 | if (!s.ok()) { |
| 10314 | ✗ | return row_info.tx->set_status_error(table->in_use, s, kd, m_tbl_def); | |
| 10315 | } | ||
| 10316 | |||
| 10317 | /* | ||
| 10318 | If the old and new keys are the same we're done since we've already taken | ||
| 10319 | the lock on the old key | ||
| 10320 | */ | ||
| 10321 |
3/4✓ Branch 0 taken 2772 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2415 times.
✓ Branch 3 taken 357 times.
|
2772 | if (!new_slice.compare(old_slice)) { |
| 10322 | 2415 | return HA_EXIT_SUCCESS; | |
| 10323 | } | ||
| 10324 |
2/2✓ Branch 0 taken 357 times.
✓ Branch 1 taken 2415 times.
|
2772 | } |
| 10325 | |||
| 10326 | /* | ||
| 10327 | Perform a read to determine if a duplicate entry exists - since this is | ||
| 10328 | a secondary indexes a range scan is needed. | ||
| 10329 | |||
| 10330 | note: we intentionally don't set options.snapshot here. We want to read | ||
| 10331 | the latest committed data. | ||
| 10332 | */ | ||
| 10333 | |||
| 10334 | 10099 | const bool all_parts_used = (user_defined_key_parts == kd.get_key_parts()); | |
| 10335 | |||
| 10336 | /* | ||
| 10337 | This iterator seems expensive since we need to allocate and free | ||
| 10338 | memory for each unique index. | ||
| 10339 | |||
| 10340 | If this needs to be optimized, for keys without NULL fields, the | ||
| 10341 | extended primary key fields can be migrated to the value portion of the | ||
| 10342 | key. This enables using Get() instead of Seek() as in the primary key | ||
| 10343 | case. | ||
| 10344 | |||
| 10345 | The bloom filter may need to be disabled for this lookup. | ||
| 10346 | */ | ||
| 10347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10099 times.
|
10099 | assert(!m_key_descr_arr[key_id]->is_partial_index()); |
| 10348 | 20198 | Rdb_iterator_base iter(ha_thd(), m_key_descr_arr[key_id], m_pk_descr, | |
| 10349 |
2/4✓ Branch 0 taken 10099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10099 times.
✗ Branch 3 not taken.
|
20198 | m_tbl_def); |
| 10350 | |||
| 10351 | /* | ||
| 10352 | If all_parts_used is true, then PK uniqueness check/lock would already | ||
| 10353 | guarantee SK uniqueness. We could optimize this by calling non-locking | ||
| 10354 | get instead. | ||
| 10355 | */ | ||
| 10356 | 10099 | bool skip_ttl_check = !all_parts_used; | |
| 10357 |
3/4✓ Branch 0 taken 612 times.
✓ Branch 1 taken 9487 times.
✓ Branch 2 taken 10099 times.
✗ Branch 3 not taken.
|
10099 | rc = iter.get(&new_slice, all_parts_used ? &m_retrieved_record : nullptr, |
| 10358 | m_lock_rows, skip_ttl_check); | ||
| 10359 |
4/4✓ Branch 0 taken 3702 times.
✓ Branch 1 taken 6397 times.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 3612 times.
|
10099 | if (rc && rc != HA_ERR_KEY_NOT_FOUND) { |
| 10360 | 90 | return rc; | |
| 10361 | } | ||
| 10362 | |||
| 10363 |
2/2✓ Branch 0 taken 9397 times.
✓ Branch 1 taken 612 times.
|
10009 | if (!all_parts_used) { |
| 10364 |
1/2✓ Branch 0 taken 9397 times.
✗ Branch 1 not taken.
|
9397 | rc = iter.seek(HA_READ_KEY_EXACT, new_slice, false /* full_key_match */, |
| 10365 | new_slice, true /* read current */); | ||
| 10366 | |||
| 10367 |
3/4✓ Branch 0 taken 8788 times.
✓ Branch 1 taken 609 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8788 times.
|
9397 | if (rc && rc != HA_ERR_END_OF_FILE) { |
| 10368 | ✗ | return rc; | |
| 10369 | } | ||
| 10370 | } | ||
| 10371 | |||
| 10372 | 10009 | *found = (rc == HA_EXIT_SUCCESS); | |
| 10373 | |||
| 10374 | 10009 | rc = HA_EXIT_SUCCESS; | |
| 10375 |
4/4✓ Branch 0 taken 609 times.
✓ Branch 1 taken 9400 times.
✓ Branch 2 taken 216 times.
✓ Branch 3 taken 393 times.
|
10009 | if (*found && m_insert_with_update) { |
| 10376 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
✓ Branch 2 taken 216 times.
✗ Branch 3 not taken.
|
216 | const rocksdb::Slice &rkey = all_parts_used ? new_slice : iter.key(); |
| 10377 | uint pk_size = | ||
| 10378 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | kd.get_primary_key_tuple(*m_pk_descr, &rkey, m_pk_packed_tuple); |
| 10379 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
|
216 | if (pk_size == RDB_INVALID_KEY_LEN) { |
| 10380 | ✗ | rc = HA_ERR_ROCKSDB_CORRUPT_DATA; | |
| 10381 | } else { | ||
| 10382 | 216 | m_dup_key_found = true; | |
| 10383 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | m_last_rowkey.copy((const char *)m_pk_packed_tuple, pk_size, |
| 10384 | &my_charset_bin); | ||
| 10385 | #ifndef NDEBUG | ||
| 10386 | // save it for sanity checking later | ||
| 10387 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | m_dup_key_tuple.copy(rkey.data(), rkey.size(), &my_charset_bin); |
| 10388 | #endif | ||
| 10389 | } | ||
| 10390 | } | ||
| 10391 | |||
| 10392 | 10009 | return rc; | |
| 10393 | 10099 | } | |
| 10394 | |||
| 10395 | /** | ||
| 10396 | Enumerate all keys to check their uniquess and also lock it | ||
| 10397 | |||
| 10398 | @param[in] row_info hold all data for update row, such as old row | ||
| 10399 | data and new row data | ||
| 10400 | @param[out] pk_changed whether primary key is changed | ||
| 10401 | @return | ||
| 10402 | HA_EXIT_SUCCESS OK | ||
| 10403 | other HA_ERR error code (can be SE-specific) | ||
| 10404 | */ | ||
| 10405 | 8466778 | int ha_rocksdb::check_uniqueness_and_lock( | |
| 10406 | const struct update_row_info &row_info, bool pk_changed, | ||
| 10407 | bool skip_unique_check) { | ||
| 10408 | 8466778 | Rdb_transaction *const tx = get_or_create_tx(ha_thd()); | |
| 10409 | 8587851 | tx->acquire_snapshot(false); | |
| 10410 | |||
| 10411 | /* | ||
| 10412 | Go through each index and determine if the index has uniqueness | ||
| 10413 | requirements. If it does, then try to obtain a row lock on the new values. | ||
| 10414 | Once all locks have been obtained, then perform the changes needed to | ||
| 10415 | update/insert the row. | ||
| 10416 | */ | ||
| 10417 |
2/2✓ Branch 0 taken 20992503 times.
✓ Branch 1 taken 8575494 times.
|
29567997 | for (uint key_id = 0; key_id < m_tbl_def->m_key_count; key_id++) { |
| 10418 | bool found; | ||
| 10419 | int rc; | ||
| 10420 | |||
| 10421 |
4/6✓ Branch 0 taken 21000745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 21000742 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
20992503 | DBUG_EXECUTE_IF("rocksdb_blob_crash", |
| 10422 | DBUG_SET("+d,rocksdb_check_uniqueness");); | ||
| 10423 |
3/4✓ Branch 0 taken 20998607 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8498002 times.
✓ Branch 3 taken 12500605 times.
|
21000745 | if (is_pk(key_id, table, m_tbl_def)) { |
| 10424 |
6/6✓ Branch 0 taken 265727 times.
✓ Branch 1 taken 8236656 times.
✓ Branch 2 taken 122255 times.
✓ Branch 3 taken 143472 times.
✓ Branch 4 taken 122255 times.
✓ Branch 5 taken 8380128 times.
|
8498002 | if (row_info.old_pk_slice.size() > 0 && !pk_changed) { |
| 10425 | 122255 | found = false; | |
| 10426 | 122255 | rc = HA_EXIT_SUCCESS; | |
| 10427 | } else { | ||
| 10428 |
1/2✓ Branch 0 taken 8398126 times.
✗ Branch 1 not taken.
|
8380128 | rc = check_and_lock_unique_pk(row_info, &found, skip_unique_check); |
| 10429 |
3/6✓ Branch 0 taken 8403215 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8442235 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8476294 times.
✗ Branch 5 not taken.
|
8398126 | DEBUG_SYNC(ha_thd(), "rocksdb.after_unique_pk_check"); |
| 10430 | } | ||
| 10431 | } else { | ||
| 10432 |
1/2✓ Branch 0 taken 12503856 times.
✗ Branch 1 not taken.
|
12500605 | rc = check_and_lock_sk(key_id, row_info, &found, skip_unique_check); |
| 10433 |
3/6✓ Branch 0 taken 12503856 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12503856 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12503856 times.
✗ Branch 5 not taken.
|
12503856 | DEBUG_SYNC(ha_thd(), "rocksdb.after_unique_sk_check"); |
| 10434 | } | ||
| 10435 |
3/6✓ Branch 0 taken 21095699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 21095696 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
21095721 | DBUG_EXECUTE_IF("rocksdb_blob_crash", |
| 10436 | DBUG_SET("-d,rocksdb_check_uniqueness");); | ||
| 10437 | |||
| 10438 |
2/2✓ Branch 0 taken 148 times.
✓ Branch 1 taken 21078572 times.
|
21078720 | if (rc != HA_EXIT_SUCCESS) { |
| 10439 | 3219 | return rc; | |
| 10440 | } | ||
| 10441 | |||
| 10442 |
2/2✓ Branch 0 taken 3071 times.
✓ Branch 1 taken 21075501 times.
|
21078572 | if (found) { |
| 10443 | /* There is a row with this key already, so error out. */ | ||
| 10444 | 3071 | errkey = key_id; | |
| 10445 | 3071 | m_dupp_errkey = errkey; | |
| 10446 | |||
| 10447 | 3071 | return HA_ERR_FOUND_DUPP_KEY; | |
| 10448 | } | ||
| 10449 | } | ||
| 10450 | |||
| 10451 | 8575494 | return HA_EXIT_SUCCESS; | |
| 10452 | } | ||
| 10453 | |||
| 10454 | 68234657 | int ha_rocksdb::bulk_load_key(Rdb_transaction *const tx, const Rdb_key_def &kd, | |
| 10455 | const rocksdb::Slice &key, | ||
| 10456 | const rocksdb::Slice &value, bool sort) { | ||
| 10457 |
1/2✓ Branch 0 taken 68234657 times.
✗ Branch 1 not taken.
|
68234657 | DBUG_ENTER_FUNC(); |
| 10458 | int res; | ||
| 10459 |
1/2✓ Branch 0 taken 68234657 times.
✗ Branch 1 not taken.
|
68234657 | THD *thd = ha_thd(); |
| 10460 |
3/6✓ Branch 0 taken 68234657 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68234657 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 68234657 times.
|
68234657 | if (thd && thd->killed) { |
| 10461 | ✗ | DBUG_RETURN(HA_ERR_QUERY_INTERRUPTED); | |
| 10462 | } | ||
| 10463 | |||
| 10464 | 68234657 | rocksdb::ColumnFamilyHandle *cf = kd.get_cf(); | |
| 10465 | |||
| 10466 | // In the case of unsorted inserts, m_sst_info allocated here is not | ||
| 10467 | // used to store the keys. It is still used to indicate when tables | ||
| 10468 | // are switched. | ||
| 10469 |
6/6✓ Branch 0 taken 68234104 times.
✓ Branch 1 taken 553 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 68234068 times.
✓ Branch 4 taken 589 times.
✓ Branch 5 taken 68234068 times.
|
68234657 | if (m_sst_info == nullptr || m_sst_info->is_done()) { |
| 10470 |
2/4✓ Branch 0 taken 589 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 589 times.
✗ Branch 3 not taken.
|
1178 | m_sst_info.reset(new Rdb_sst_info(rdb, m_table_handler->m_table_name, |
| 10471 | 589 | kd.get_name(), cf, *rocksdb_db_options, | |
| 10472 |
4/8✓ Branch 0 taken 589 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 589 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 589 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 589 times.
✗ Branch 7 not taken.
|
589 | THDVAR(ha_thd(), trace_sst_api))); |
| 10473 |
1/2✓ Branch 0 taken 589 times.
✗ Branch 1 not taken.
|
589 | res = tx->start_bulk_load(this, m_sst_info); |
| 10474 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 586 times.
|
589 | if (res != HA_EXIT_SUCCESS) { |
| 10475 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(res); |
| 10476 | } | ||
| 10477 | } | ||
| 10478 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68234654 times.
|
68234654 | assert(m_sst_info); |
| 10479 | |||
| 10480 |
2/2✓ Branch 0 taken 24080865 times.
✓ Branch 1 taken 44153789 times.
|
68234654 | if (sort) { |
| 10481 | Rdb_index_merge *key_merge; | ||
| 10482 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24080865 times.
|
24080865 | assert(cf != nullptr); |
| 10483 | |||
| 10484 |
2/4✓ Branch 0 taken 24080865 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24080865 times.
✗ Branch 3 not taken.
|
24080865 | res = tx->get_key_merge(kd.get_gl_index_id(), cf, &key_merge); |
| 10485 |
1/2✓ Branch 0 taken 24080865 times.
✗ Branch 1 not taken.
|
24080865 | if (res == HA_EXIT_SUCCESS) { |
| 10486 |
1/2✓ Branch 0 taken 24080865 times.
✗ Branch 1 not taken.
|
24080865 | res = key_merge->add(key, value); |
| 10487 | } | ||
| 10488 | } else { | ||
| 10489 |
1/2✓ Branch 0 taken 44153789 times.
✗ Branch 1 not taken.
|
44153789 | res = m_sst_info->put(key, value); |
| 10490 | } | ||
| 10491 | |||
| 10492 |
1/2✓ Branch 0 taken 68234654 times.
✗ Branch 1 not taken.
|
68234654 | DBUG_RETURN(res); |
| 10493 | } | ||
| 10494 | |||
| 10495 | 131845 | int ha_rocksdb::finalize_bulk_load(bool print_client_error) { | |
| 10496 |
1/2✓ Branch 0 taken 131845 times.
✗ Branch 1 not taken.
|
131845 | DBUG_ENTER_FUNC(); |
| 10497 | |||
| 10498 | 131845 | int res = HA_EXIT_SUCCESS; | |
| 10499 | |||
| 10500 | /* Skip if there are no possible ongoing bulk loads */ | ||
| 10501 |
2/2✓ Branch 0 taken 538 times.
✓ Branch 1 taken 131307 times.
|
131845 | if (m_sst_info) { |
| 10502 |
2/2✓ Branch 0 taken 522 times.
✓ Branch 1 taken 16 times.
|
538 | if (m_sst_info->is_done()) { |
| 10503 | 522 | m_sst_info.reset(); | |
| 10504 |
1/2✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
|
522 | DBUG_RETURN(res); |
| 10505 | } | ||
| 10506 | |||
| 10507 | 16 | Rdb_sst_info::Rdb_sst_commit_info commit_info; | |
| 10508 | |||
| 10509 | // Wrap up the current work in m_sst_info and get ready to commit | ||
| 10510 | // This transfer the responsibility of commit over to commit_info | ||
| 10511 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | res = m_sst_info->finish(&commit_info, print_client_error); |
| 10512 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (res == 0) { |
| 10513 | // Make sure we have work to do - under race condition we could lose | ||
| 10514 | // to another thread and end up with no work | ||
| 10515 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
|
16 | if (commit_info.has_work()) { |
| 10516 | 7 | rocksdb::IngestExternalFileOptions opts; | |
| 10517 | 7 | opts.move_files = true; | |
| 10518 | 7 | opts.snapshot_consistency = false; | |
| 10519 | 7 | opts.allow_global_seqno = false; | |
| 10520 | 7 | opts.allow_blocking_flush = false; | |
| 10521 | |||
| 10522 | 7 | const rocksdb::Status s = rdb->IngestExternalFile( | |
| 10523 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | commit_info.get_cf(), commit_info.get_committed_files(), opts); |
| 10524 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | if (!s.ok()) { |
| 10525 | ✗ | if (print_client_error) { | |
| 10526 | ✗ | Rdb_sst_info::report_error_msg(s, nullptr); | |
| 10527 | } | ||
| 10528 | ✗ | res = HA_ERR_ROCKSDB_BULK_LOAD; | |
| 10529 | } else { | ||
| 10530 | // Mark the list of SST files as committed, otherwise they'll get | ||
| 10531 | // cleaned up when commit_info destructs | ||
| 10532 | 7 | commit_info.commit(); | |
| 10533 | } | ||
| 10534 | 7 | } | |
| 10535 | } | ||
| 10536 | 16 | m_sst_info.reset(); | |
| 10537 | 16 | } | |
| 10538 |
1/2✓ Branch 0 taken 131323 times.
✗ Branch 1 not taken.
|
131323 | DBUG_RETURN(res); |
| 10539 | } | ||
| 10540 | |||
| 10541 | /** | ||
| 10542 | Update an existing primary key record or write a new primary key record | ||
| 10543 | |||
| 10544 | @param[in] kd the primary key is being update/write | ||
| 10545 | @param[in] update_row_info hold all row data, such as old row data and | ||
| 10546 | new row data | ||
| 10547 | @param[in] pk_changed whether primary key is changed | ||
| 10548 | @return | ||
| 10549 | HA_EXIT_SUCCESS OK | ||
| 10550 | Other HA_ERR error code (can be SE-specific) | ||
| 10551 | */ | ||
| 10552 | 70672862 | int ha_rocksdb::update_write_pk(const Rdb_key_def &kd, | |
| 10553 | const struct update_row_info &row_info, | ||
| 10554 | const bool pk_changed) { | ||
| 10555 | 70672862 | const uint key_id = kd.get_keyno(); | |
| 10556 |
1/2✓ Branch 0 taken 70678909 times.
✗ Branch 1 not taken.
|
70670840 | const bool hidden_pk = is_hidden_pk(key_id, table, m_tbl_def); |
| 10557 | |||
| 10558 | /* | ||
| 10559 | If the PK has changed, or if this PK uses single deletes and this is an | ||
| 10560 | update, the old key needs to be deleted. In the single delete case, it | ||
| 10561 | might be possible to have this sequence of keys: PUT(X), PUT(X), SD(X), | ||
| 10562 | resulting in the first PUT(X) showing up. | ||
| 10563 | */ | ||
| 10564 |
8/8✓ Branch 0 taken 70261802 times.
✓ Branch 1 taken 417107 times.
✓ Branch 2 taken 70120014 times.
✓ Branch 3 taken 141788 times.
✓ Branch 4 taken 98662 times.
✓ Branch 5 taken 70022359 times.
✓ Branch 6 taken 143428 times.
✓ Branch 7 taken 70542041 times.
|
70783124 | if (!hidden_pk && (pk_changed || ((row_info.old_pk_slice.size() > 0) && |
| 10565 |
3/4✓ Branch 0 taken 104215 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1640 times.
✓ Branch 3 taken 102575 times.
|
98662 | can_use_single_delete(key_id)))) { |
| 10566 | const rocksdb::Status s = delete_or_singledelete( | ||
| 10567 |
1/2✓ Branch 0 taken 143428 times.
✗ Branch 1 not taken.
|
143428 | key_id, row_info.tx, kd.get_cf(), row_info.old_pk_slice); |
| 10568 |
2/4✓ Branch 0 taken 143428 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143428 times.
|
143428 | if (!s.ok()) { |
| 10569 | ✗ | return row_info.tx->set_status_error(table->in_use, s, kd, m_tbl_def); | |
| 10570 | } | ||
| 10571 |
1/2✓ Branch 0 taken 143428 times.
✗ Branch 1 not taken.
|
143428 | } |
| 10572 | |||
| 10573 |
2/2✓ Branch 0 taken 8181541 times.
✓ Branch 1 taken 62503928 times.
|
70685469 | if (table->found_next_number_field) { |
| 10574 |
1/2✓ Branch 0 taken 8150014 times.
✗ Branch 1 not taken.
|
8181541 | update_auto_incr_val_from_field(); |
| 10575 | } | ||
| 10576 | |||
| 10577 | 70653942 | int rc = HA_EXIT_SUCCESS; | |
| 10578 | 70653942 | rocksdb::Slice value_slice; | |
| 10579 | /* Prepare the new record to be written into RocksDB */ | ||
| 10580 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70654776 times.
|
141306138 | if ((rc = m_converter->encode_value_slice( |
| 10581 | 70636038 | m_pk_descr, row_info.new_pk_slice, row_info.new_pk_unpack_info, | |
| 10582 |
1/2✓ Branch 0 taken 70654776 times.
✗ Branch 1 not taken.
|
70666291 | !row_info.old_pk_slice.empty(), should_store_row_debug_checksums(), |
| 10583 | m_ttl_bytes, &m_ttl_bytes_updated, &value_slice))) { | ||
| 10584 | ✗ | return rc; | |
| 10585 | } | ||
| 10586 | |||
| 10587 | 70654776 | const auto cf = m_pk_descr->get_cf(); | |
| 10588 |
6/8✓ Branch 0 taken 70679528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70711384 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 62153954 times.
✓ Branch 5 taken 8557430 times.
✓ Branch 6 taken 62153954 times.
✓ Branch 7 taken 8535071 times.
|
132811123 | if (rocksdb_enable_bulk_load_api && THDVAR(table->in_use, bulk_load) && |
| 10589 |
1/2✓ Branch 0 taken 62153954 times.
✗ Branch 1 not taken.
|
62153954 | !hidden_pk) { |
| 10590 | /* | ||
| 10591 | Write the primary key directly to an SST file using an SstFileWriter | ||
| 10592 | */ | ||
| 10593 | 62153954 | rc = bulk_load_key(row_info.tx, kd, row_info.new_pk_slice, value_slice, | |
| 10594 |
2/4✓ Branch 0 taken 62153954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62153954 times.
✗ Branch 3 not taken.
|
62153954 | THDVAR(table->in_use, bulk_load_allow_unsorted)); |
| 10595 |
4/4✓ Branch 0 taken 8533122 times.
✓ Branch 1 taken 1949 times.
✓ Branch 2 taken 1095870 times.
✓ Branch 3 taken 7437252 times.
|
8535071 | } else if (row_info.skip_unique_check || row_info.tx->m_ddl_transaction) { |
| 10596 | /* | ||
| 10597 | It is responsibility of the user to make sure that the data being | ||
| 10598 | inserted doesn't violate any unique keys. | ||
| 10599 | */ | ||
| 10600 |
2/4✓ Branch 0 taken 1078734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1078734 times.
✗ Branch 3 not taken.
|
1097819 | row_info.tx->get_indexed_write_batch()->Put(cf, row_info.new_pk_slice, |
| 10601 | value_slice); | ||
| 10602 | } else { | ||
| 10603 |
2/4✓ Branch 0 taken 7468812 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7504333 times.
✗ Branch 3 not taken.
|
7437252 | const bool assume_tracked = can_assume_tracked(ha_thd()); |
| 10604 | 7504333 | const auto s = row_info.tx->put(cf, row_info.new_pk_slice, value_slice, | |
| 10605 |
1/2✓ Branch 0 taken 7478555 times.
✗ Branch 1 not taken.
|
7504333 | assume_tracked); |
| 10606 |
3/4✓ Branch 0 taken 7491984 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7491982 times.
|
7478555 | if (!s.ok()) { |
| 10607 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (s.IsBusy()) { |
| 10608 | ✗ | errkey = table->s->primary_key; | |
| 10609 | ✗ | m_dupp_errkey = errkey; | |
| 10610 | ✗ | rc = HA_ERR_FOUND_DUPP_KEY; | |
| 10611 | } else { | ||
| 10612 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | rc = row_info.tx->set_status_error(table->in_use, s, *m_pk_descr, |
| 10613 | 2 | m_tbl_def); | |
| 10614 | } | ||
| 10615 | } | ||
| 10616 | 7491984 | } | |
| 10617 | |||
| 10618 | 70728315 | return rc; | |
| 10619 | } | ||
| 10620 | |||
| 10621 | /** | ||
| 10622 | update an existing secondary key record or write a new secondary key record | ||
| 10623 | |||
| 10624 | @param[in] table_arg Table we're working on | ||
| 10625 | @param[in] kd The secondary key being update/write | ||
| 10626 | @param[in] row_info data structure contains old row data and new row data | ||
| 10627 | @param[in] bulk_load_sk whether support bulk load. Currently it is only | ||
| 10628 | support for write | ||
| 10629 | @return | ||
| 10630 | HA_EXIT_SUCCESS OK | ||
| 10631 | Other HA_ERR error code (can be SE-specific) | ||
| 10632 | */ | ||
| 10633 | 53054461 | int ha_rocksdb::update_write_sk(const TABLE *const table_arg, | |
| 10634 | const Rdb_key_def &kd, | ||
| 10635 | const struct update_row_info &row_info, | ||
| 10636 | const bool bulk_load_sk) { | ||
| 10637 | int new_packed_size; | ||
| 10638 | int old_packed_size; | ||
| 10639 | 53054461 | int rc = HA_EXIT_SUCCESS; | |
| 10640 | |||
| 10641 | 53054461 | rocksdb::Slice new_key_slice; | |
| 10642 | 53054462 | rocksdb::Slice new_value_slice; | |
| 10643 | 53054462 | rocksdb::Slice old_key_slice; | |
| 10644 | |||
| 10645 | 53054462 | const uint key_id = kd.get_keyno(); | |
| 10646 | /* | ||
| 10647 | Can skip updating this key if none of the key fields have changed and, if | ||
| 10648 | this table has TTL, the TTL timestamp has not changed. | ||
| 10649 | */ | ||
| 10650 |
6/6✓ Branch 0 taken 286940 times.
✓ Branch 1 taken 52767522 times.
✓ Branch 2 taken 600 times.
✓ Branch 3 taken 286340 times.
✓ Branch 4 taken 600 times.
✓ Branch 5 taken 53053862 times.
|
53055062 | if (row_info.old_data != nullptr && !m_update_scope.is_set(key_id) && |
| 10651 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
600 | (!kd.has_ttl() || !m_ttl_bytes_updated)) { |
| 10652 | 600 | return HA_EXIT_SUCCESS; | |
| 10653 | } | ||
| 10654 | |||
| 10655 | 53053862 | bool store_row_debug_checksums = should_store_row_debug_checksums(); | |
| 10656 | 53053862 | new_packed_size = | |
| 10657 | 106107724 | kd.pack_record(table_arg, m_pack_buffer, row_info.new_data, | |
| 10658 | m_sk_packed_tuple, &m_sk_tails, store_row_debug_checksums, | ||
| 10659 |
1/2✓ Branch 0 taken 53053862 times.
✗ Branch 1 not taken.
|
53053862 | row_info.hidden_pk_id, 0, nullptr, m_ttl_bytes); |
| 10660 | |||
| 10661 |
2/2✓ Branch 0 taken 286340 times.
✓ Branch 1 taken 52767522 times.
|
53053862 | if (row_info.old_data != nullptr) { |
| 10662 | // The old value | ||
| 10663 | 572680 | old_packed_size = kd.pack_record( | |
| 10664 | 286340 | table_arg, m_pack_buffer, row_info.old_data, m_sk_packed_tuple_old, | |
| 10665 | 286340 | &m_sk_tails_old, store_row_debug_checksums, row_info.hidden_pk_id, 0, | |
| 10666 |
1/2✓ Branch 0 taken 286340 times.
✗ Branch 1 not taken.
|
286340 | nullptr, m_ttl_bytes); |
| 10667 | |||
| 10668 | /* | ||
| 10669 | Check if we are going to write the same value. This can happen when | ||
| 10670 | one does | ||
| 10671 | UPDATE tbl SET col='foo' | ||
| 10672 | and we are looking at the row that already has col='foo'. | ||
| 10673 | |||
| 10674 | We also need to compare the unpack info. Suppose, the collation is | ||
| 10675 | case-insensitive, and unpack info contains information about whether | ||
| 10676 | the letters were uppercase and lowercase. Then, both 'foo' and 'FOO' | ||
| 10677 | will have the same key value, but different data in unpack_info. | ||
| 10678 | |||
| 10679 | (note: anyone changing bytewise_compare should take this code into | ||
| 10680 | account) | ||
| 10681 | */ | ||
| 10682 |
2/2✓ Branch 0 taken 286330 times.
✓ Branch 1 taken 1 times.
|
286331 | if (old_packed_size == new_packed_size && |
| 10683 | 286331 | m_sk_tails_old.get_current_pos() == m_sk_tails.get_current_pos() && | |
| 10684 |
4/4✓ Branch 0 taken 120 times.
✓ Branch 1 taken 286210 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 60 times.
|
286330 | !(kd.has_ttl() && m_ttl_bytes_updated) && |
| 10685 |
2/2✓ Branch 0 taken 67390 times.
✓ Branch 1 taken 218880 times.
|
286270 | memcmp(m_sk_packed_tuple_old, m_sk_packed_tuple, old_packed_size) == |
| 10686 |
4/4✓ Branch 0 taken 286331 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 67390 times.
✓ Branch 3 taken 218950 times.
|
572671 | 0 && |
| 10687 |
1/2✓ Branch 0 taken 67390 times.
✗ Branch 1 not taken.
|
67390 | memcmp(m_sk_tails_old.ptr(), m_sk_tails.ptr(), |
| 10688 | m_sk_tails.get_current_pos()) == 0) { | ||
| 10689 | 67390 | return HA_EXIT_SUCCESS; | |
| 10690 | } | ||
| 10691 | |||
| 10692 | /* | ||
| 10693 | Deleting entries from secondary index should skip locking, but | ||
| 10694 | be visible to the transaction. | ||
| 10695 | (also note that DDL statements do not delete rows, so this is not a DDL | ||
| 10696 | statement) | ||
| 10697 | */ | ||
| 10698 | 437900 | old_key_slice = rocksdb::Slice( | |
| 10699 | 218950 | reinterpret_cast<const char *>(m_sk_packed_tuple_old), old_packed_size); | |
| 10700 | |||
| 10701 | // TODO(mung) - If the new_data and old_data below to the same partial index | ||
| 10702 | // group (ie. have the same prefix), we can make use of the read below to | ||
| 10703 | // determine whether to issue SingleDelete or not. | ||
| 10704 | // | ||
| 10705 | // Currently we unconditionally issue SingleDelete, meaning that it is | ||
| 10706 | // possible for SD to be compacted out without meeting any Puts. This bumps | ||
| 10707 | // the num_single_delete_fallthrough counter in rocksdb, but is otherwise | ||
| 10708 | // fine as the SD markers just get compacted out. We will have to revisit | ||
| 10709 | // this if we want stronger consistency checks though. | ||
| 10710 |
2/4✓ Branch 0 taken 218950 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218950 times.
✗ Branch 3 not taken.
|
218950 | row_info.tx->get_indexed_write_batch()->SingleDelete(kd.get_cf(), |
| 10711 | old_key_slice); | ||
| 10712 | } | ||
| 10713 | |||
| 10714 |
6/6✓ Branch 0 taken 18930 times.
✓ Branch 1 taken 52967541 times.
✓ Branch 2 taken 18270 times.
✓ Branch 3 taken 660 times.
✓ Branch 4 taken 18270 times.
✓ Branch 5 taken 52968201 times.
|
52986472 | if (kd.is_partial_index() && !bulk_load_sk) { |
| 10715 | // TODO(mung) - We've already calculated prefix len when locking. If we | ||
| 10716 | // cache that value, we can avoid recalculating here. | ||
| 10717 |
1/2✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
|
18270 | int size = kd.pack_record(table_arg, m_pack_buffer, row_info.new_data, |
| 10718 | m_sk_packed_tuple, nullptr, false, 0, | ||
| 10719 | 18270 | kd.partial_index_keyparts()); | |
| 10720 | const rocksdb::Slice prefix_slice = | ||
| 10721 | 18270 | rocksdb::Slice((const char *)m_sk_packed_tuple, size); | |
| 10722 | |||
| 10723 |
1/2✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
|
18270 | rocksdb::PinnableSlice value; |
| 10724 | 18270 | const rocksdb::Status s = row_info.tx->get_for_update( | |
| 10725 | kd, prefix_slice, &value, false /* exclusive */, | ||
| 10726 |
1/2✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
|
18270 | false /* do validate */, false /* no_wait */); |
| 10727 |
5/10✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18270 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18270 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18270 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18270 times.
|
18270 | if (!s.ok() && !s.IsNotFound()) { |
| 10728 | ✗ | return row_info.tx->set_status_error(table_arg->in_use, s, kd, m_tbl_def); | |
| 10729 | } | ||
| 10730 | |||
| 10731 | // We can skip updating the index, if the prefix is not materialized. | ||
| 10732 |
2/4✓ Branch 0 taken 18270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18270 times.
✗ Branch 3 not taken.
|
18270 | if (s.IsNotFound()) { |
| 10733 | 18270 | return 0; | |
| 10734 | } | ||
| 10735 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 18270 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18270 times.
|
36540 | } |
| 10736 | |||
| 10737 | 105936402 | new_key_slice = rocksdb::Slice( | |
| 10738 | 52968201 | reinterpret_cast<const char *>(m_sk_packed_tuple), new_packed_size); | |
| 10739 | 52968202 | new_value_slice = | |
| 10740 | 52968201 | rocksdb::Slice(reinterpret_cast<const char *>(m_sk_tails.ptr()), | |
| 10741 | m_sk_tails.get_current_pos()); | ||
| 10742 | |||
| 10743 |
3/4✓ Branch 0 taken 1501500 times.
✓ Branch 1 taken 51466702 times.
✓ Branch 2 taken 1501500 times.
✗ Branch 3 not taken.
|
52968202 | if (bulk_load_sk && row_info.old_data == nullptr) { |
| 10744 |
1/2✓ Branch 0 taken 1501500 times.
✗ Branch 1 not taken.
|
1501500 | rc = bulk_load_key(row_info.tx, kd, new_key_slice, new_value_slice, true); |
| 10745 | } else { | ||
| 10746 |
2/4✓ Branch 0 taken 51466702 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51466702 times.
✗ Branch 3 not taken.
|
51466702 | row_info.tx->get_indexed_write_batch()->Put(kd.get_cf(), new_key_slice, |
| 10747 | new_value_slice); | ||
| 10748 | } | ||
| 10749 | |||
| 10750 | 52968202 | return rc; | |
| 10751 | } | ||
| 10752 | |||
| 10753 | /** | ||
| 10754 | Update existing indexes(PK/SKs) or write new indexes(PK/SKs) | ||
| 10755 | |||
| 10756 | @param[in] row_info hold all row data, such as old key/new key | ||
| 10757 | @param[in] pk_changed whether primary key is changed | ||
| 10758 | @return | ||
| 10759 | HA_EXIT_SUCCESS OK | ||
| 10760 | Other HA_ERR error code (can be SE-specific) | ||
| 10761 | */ | ||
| 10762 | 70707933 | int ha_rocksdb::update_write_indexes(const struct update_row_info &row_info, | |
| 10763 | const bool pk_changed) { | ||
| 10764 | int rc; | ||
| 10765 | bool bulk_load_sk; | ||
| 10766 | |||
| 10767 | // The PK must be updated first to pull out the TTL value. | ||
| 10768 | 70707933 | rc = update_write_pk(*m_pk_descr, row_info, pk_changed); | |
| 10769 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 70710628 times.
|
70710639 | if (rc != HA_EXIT_SUCCESS) { |
| 10770 | 11 | return rc; | |
| 10771 | } | ||
| 10772 | |||
| 10773 | // Update the remaining indexes. Allow bulk loading only if | ||
| 10774 | // allow_sk is enabled | ||
| 10775 | 141466136 | bulk_load_sk = rocksdb_enable_bulk_load_api && | |
| 10776 |
3/4✓ Branch 0 taken 70715528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62146203 times.
✓ Branch 3 taken 8585444 times.
|
132864573 | THDVAR(table->in_use, bulk_load) && |
| 10777 |
2/2✓ Branch 0 taken 1500750 times.
✓ Branch 1 taken 60653195 times.
|
62146203 | THDVAR(table->in_use, bulk_load_allow_sk); |
| 10778 |
2/2✓ Branch 0 taken 123788279 times.
✓ Branch 1 taken 70729145 times.
|
194517424 | for (uint key_id = 0; key_id < m_tbl_def->m_key_count; key_id++) { |
| 10779 |
2/2✓ Branch 0 taken 70725769 times.
✓ Branch 1 taken 53053427 times.
|
123788279 | if (is_pk(key_id, table, m_tbl_def)) { |
| 10780 | 70725769 | continue; | |
| 10781 | } | ||
| 10782 | |||
| 10783 | 53053427 | rc = update_write_sk(table, *m_key_descr_arr[key_id], row_info, | |
| 10784 | bulk_load_sk); | ||
| 10785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53057166 times.
|
53057166 | if (rc != HA_EXIT_SUCCESS) { |
| 10786 | ✗ | return rc; | |
| 10787 | } | ||
| 10788 | } | ||
| 10789 | |||
| 10790 | 70729145 | return HA_EXIT_SUCCESS; | |
| 10791 | } | ||
| 10792 | |||
| 10793 | /** | ||
| 10794 | Update an existing row or write a new row | ||
| 10795 | |||
| 10796 | @param[in] old_data nullptr for write, non-null for update | ||
| 10797 | @param[in] new_data non-null for write/update | ||
| 10798 | @param[in] skip_unique_check whether to check uniqueness | ||
| 10799 | @return | ||
| 10800 | HA_EXIT_SUCCESS OK | ||
| 10801 | Other HA_ERR error code (can be SE-specific) | ||
| 10802 | */ | ||
| 10803 | 70672411 | int ha_rocksdb::update_write_row(const uchar *const old_data, | |
| 10804 | const uchar *const new_data, | ||
| 10805 | const bool skip_unique_check) { | ||
| 10806 |
1/2✓ Branch 0 taken 70753620 times.
✗ Branch 1 not taken.
|
70672411 | DBUG_ENTER_FUNC(); |
| 10807 | |||
| 10808 |
1/2✓ Branch 0 taken 70725693 times.
✗ Branch 1 not taken.
|
70753620 | THD *thd = ha_thd(); |
| 10809 |
6/6✓ Branch 0 taken 70723735 times.
✓ Branch 1 taken 1958 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 70726156 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 70728114 times.
|
70725693 | if (thd && thd->killed) { |
| 10810 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | DBUG_RETURN(HA_ERR_QUERY_INTERRUPTED); |
| 10811 | } | ||
| 10812 | |||
| 10813 | 70728114 | bool pk_changed = false; | |
| 10814 | 70728114 | struct update_row_info row_info; | |
| 10815 | |||
| 10816 | 70666447 | row_info.old_data = old_data; | |
| 10817 | 70666447 | row_info.new_data = new_data; | |
| 10818 | 70666447 | row_info.skip_unique_check = skip_unique_check; | |
| 10819 | 70666447 | row_info.new_pk_unpack_info = nullptr; | |
| 10820 |
1/2✓ Branch 0 taken 70664031 times.
✗ Branch 1 not taken.
|
70666447 | set_last_rowkey(old_data); |
| 10821 | |||
| 10822 |
1/2✓ Branch 0 taken 70640660 times.
✗ Branch 1 not taken.
|
70664031 | row_info.tx = get_or_create_tx(table->in_use); |
| 10823 | |||
| 10824 |
2/2✓ Branch 0 taken 265727 times.
✓ Branch 1 taken 70374933 times.
|
70640660 | if (old_data != nullptr) { |
| 10825 | 265727 | row_info.old_pk_slice = | |
| 10826 | 265727 | rocksdb::Slice(m_last_rowkey.ptr(), m_last_rowkey.length()); | |
| 10827 | |||
| 10828 | /* Determine which indexes need updating. */ | ||
| 10829 |
1/2✓ Branch 0 taken 265727 times.
✗ Branch 1 not taken.
|
265727 | calc_updated_indexes(); |
| 10830 | } | ||
| 10831 | |||
| 10832 | /* | ||
| 10833 | Get the new row key into row_info.new_pk_slice | ||
| 10834 | */ | ||
| 10835 |
1/2✓ Branch 0 taken 70626829 times.
✗ Branch 1 not taken.
|
70640660 | int rc = get_pk_for_update(&row_info); |
| 10836 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70626829 times.
|
70626829 | if (rc != HA_EXIT_SUCCESS) { |
| 10837 | ✗ | DBUG_RETURN(rc); | |
| 10838 | } | ||
| 10839 | |||
| 10840 | /* | ||
| 10841 | For UPDATEs, if the key has changed, we need to obtain a lock. INSERTs | ||
| 10842 | always require locking. | ||
| 10843 | */ | ||
| 10844 |
2/2✓ Branch 0 taken 265727 times.
✓ Branch 1 taken 70363725 times.
|
70626829 | if (row_info.old_pk_slice.size() > 0) { |
| 10845 |
1/2✓ Branch 0 taken 265727 times.
✗ Branch 1 not taken.
|
265727 | pk_changed = row_info.new_pk_slice.compare(row_info.old_pk_slice) != 0; |
| 10846 | } | ||
| 10847 | |||
| 10848 | // Case: We skip both unique checks and rows locks only when bulk load is | ||
| 10849 | // enabled or if rocksdb_skip_locks_if_skip_unique_check is ON | ||
| 10850 |
5/6✓ Branch 0 taken 70647779 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8499064 times.
✓ Branch 3 taken 62148715 times.
✓ Branch 4 taken 8499822 times.
✓ Branch 5 taken 62147957 times.
|
79128516 | if (!THDVAR(table->in_use, bulk_load) && |
| 10851 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8499058 times.
✓ Branch 2 taken 3514 times.
✗ Branch 3 not taken.
|
8499064 | (!rocksdb_skip_locks_if_skip_unique_check || !skip_unique_check)) { |
| 10852 | /* | ||
| 10853 | Check to see if we are going to have failures because of unique | ||
| 10854 | keys. Also lock the appropriate key values. | ||
| 10855 | */ | ||
| 10856 |
1/2✓ Branch 0 taken 8552663 times.
✗ Branch 1 not taken.
|
8499822 | rc = check_uniqueness_and_lock(row_info, pk_changed, skip_unique_check); |
| 10857 |
2/2✓ Branch 0 taken 3219 times.
✓ Branch 1 taken 8549444 times.
|
8552663 | if (rc != HA_EXIT_SUCCESS) { |
| 10858 |
1/2✓ Branch 0 taken 3219 times.
✗ Branch 1 not taken.
|
3219 | DBUG_RETURN(rc); |
| 10859 | } | ||
| 10860 | } | ||
| 10861 | |||
| 10862 |
3/6✓ Branch 0 taken 70725956 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70748248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70755706 times.
✗ Branch 5 not taken.
|
70697401 | DEBUG_SYNC(ha_thd(), "rocksdb.update_write_row_after_unique_check"); |
| 10863 | |||
| 10864 | /* | ||
| 10865 | At this point, all locks have been obtained, and all checks for duplicate | ||
| 10866 | keys have been performed. No further errors can be allowed to occur from | ||
| 10867 | here because updates to the transaction will be made and those updates | ||
| 10868 | cannot be easily removed without rolling back the entire transaction. | ||
| 10869 | */ | ||
| 10870 |
1/2✓ Branch 0 taken 70727571 times.
✗ Branch 1 not taken.
|
70745937 | rc = update_write_indexes(row_info, pk_changed); |
| 10871 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 70727560 times.
|
70727571 | if (rc != HA_EXIT_SUCCESS) { |
| 10872 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | DBUG_RETURN(rc); |
| 10873 | } | ||
| 10874 | |||
| 10875 |
1/2✓ Branch 0 taken 70718276 times.
✗ Branch 1 not taken.
|
70727560 | row_info.tx->log_table_write_op(m_tbl_def); |
| 10876 | |||
| 10877 |
2/4✓ Branch 0 taken 70722247 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 70722247 times.
|
70718276 | if (do_bulk_commit(row_info.tx)) { |
| 10878 | ✗ | DBUG_RETURN(HA_ERR_ROCKSDB_BULK_LOAD); | |
| 10879 | } | ||
| 10880 | |||
| 10881 |
1/2✓ Branch 0 taken 70744466 times.
✗ Branch 1 not taken.
|
70722247 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 10882 | } | ||
| 10883 | |||
| 10884 | /* | ||
| 10885 | Setting iterator upper/lower bounds for Seek/SeekForPrev. | ||
| 10886 | This makes RocksDB to avoid scanning tombstones outside of | ||
| 10887 | the given key ranges, when prefix_same_as_start=true was not passed | ||
| 10888 | (when prefix bloom filter can not be used). | ||
| 10889 | Inversing upper/lower bound is necessary on reverse order CF. | ||
| 10890 | This covers HA_READ_PREFIX_LAST* case as well. For example, | ||
| 10891 | if given query eq condition was 12 bytes and condition was | ||
| 10892 | 0x0000b3eb003f65c5e78858b8, and if doing HA_READ_PREFIX_LAST, | ||
| 10893 | eq_cond_len was 11 (see calc_eq_cond_len() for details). | ||
| 10894 | If the index was reverse order, upper bound would be | ||
| 10895 | 0x0000b3eb003f65c5e78857, and lower bound would be | ||
| 10896 | 0x0000b3eb003f65c5e78859. These cover given eq condition range. | ||
| 10897 | */ | ||
| 10898 | 218892 | static void setup_iterator_bounds(const Rdb_key_def &kd, | |
| 10899 | const rocksdb::Slice &eq_cond, | ||
| 10900 | size_t bound_len, uchar *const lower_bound, | ||
| 10901 | uchar *const upper_bound, | ||
| 10902 | rocksdb::Slice *lower_bound_slice, | ||
| 10903 | rocksdb::Slice *upper_bound_slice) { | ||
| 10904 | // If eq_cond is shorter than Rdb_key_def::INDEX_NUMBER_SIZE, we should be | ||
| 10905 | // able to get better bounds just by using index id directly. | ||
| 10906 |
2/2✓ Branch 0 taken 40985 times.
✓ Branch 1 taken 177907 times.
|
218892 | if (eq_cond.size() <= Rdb_key_def::INDEX_NUMBER_SIZE) { |
| 10907 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40985 times.
|
40985 | assert(bound_len == Rdb_key_def::INDEX_NUMBER_SIZE); |
| 10908 | uint size; | ||
| 10909 | 40985 | kd.get_infimum_key(lower_bound, &size); | |
| 10910 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40985 times.
|
40985 | assert(size == Rdb_key_def::INDEX_NUMBER_SIZE); |
| 10911 | 40985 | kd.get_supremum_key(upper_bound, &size); | |
| 10912 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40985 times.
|
40985 | assert(size == Rdb_key_def::INDEX_NUMBER_SIZE); |
| 10913 | } else { | ||
| 10914 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 177907 times.
|
177907 | assert(bound_len <= eq_cond.size()); |
| 10915 | 177907 | memcpy(upper_bound, eq_cond.data(), bound_len); | |
| 10916 | 177907 | kd.successor(upper_bound, bound_len); | |
| 10917 | 177907 | memcpy(lower_bound, eq_cond.data(), bound_len); | |
| 10918 | 177907 | kd.predecessor(lower_bound, bound_len); | |
| 10919 | } | ||
| 10920 | |||
| 10921 |
2/2✓ Branch 0 taken 62086 times.
✓ Branch 1 taken 156806 times.
|
218892 | if (kd.m_is_reverse_cf) { |
| 10922 | 62086 | *upper_bound_slice = rocksdb::Slice((const char *)lower_bound, bound_len); | |
| 10923 | 62086 | *lower_bound_slice = rocksdb::Slice((const char *)upper_bound, bound_len); | |
| 10924 | } else { | ||
| 10925 | 156806 | *upper_bound_slice = rocksdb::Slice((const char *)upper_bound, bound_len); | |
| 10926 | 156806 | *lower_bound_slice = rocksdb::Slice((const char *)lower_bound, bound_len); | |
| 10927 | } | ||
| 10928 | 218892 | } | |
| 10929 | |||
| 10930 | /** | ||
| 10931 | @return | ||
| 10932 | HA_EXIT_SUCCESS OK | ||
| 10933 | other HA_ERR error code (can be SE-specific) | ||
| 10934 | */ | ||
| 10935 | 115731 | int ha_rocksdb::rnd_init(bool scan MY_ATTRIBUTE((__unused__))) { | |
| 10936 |
1/2✓ Branch 0 taken 115731 times.
✗ Branch 1 not taken.
|
115731 | DBUG_ENTER_FUNC(); |
| 10937 | |||
| 10938 | 115731 | m_need_build_decoder = true; | |
| 10939 | 115731 | m_rnd_scan_started = false; | |
| 10940 |
6/10✓ Branch 0 taken 115731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 115731 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13465 times.
✓ Branch 5 taken 102266 times.
✓ Branch 6 taken 102266 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 115731 times.
✗ Branch 9 not taken.
|
231462 | DBUG_RETURN( |
| 10941 | index_init(has_hidden_pk(table) ? MAX_KEY : pk_index(table, m_tbl_def), | ||
| 10942 | false /* sorted */)); | ||
| 10943 | } | ||
| 10944 | |||
| 10945 | /** | ||
| 10946 | @return | ||
| 10947 | HA_EXIT_SUCCESS OK | ||
| 10948 | other HA_ERR error code (can be SE-specific) | ||
| 10949 | */ | ||
| 10950 | 97051958 | int ha_rocksdb::rnd_next(uchar *const buf) { | |
| 10951 |
1/2✓ Branch 0 taken 97051958 times.
✗ Branch 1 not taken.
|
97051958 | DBUG_ENTER_FUNC(); |
| 10952 | |||
| 10953 |
1/2✓ Branch 0 taken 97051958 times.
✗ Branch 1 not taken.
|
97051958 | check_build_decoder(); |
| 10954 | |||
| 10955 | int rc; | ||
| 10956 |
1/2✓ Branch 0 taken 97051958 times.
✗ Branch 1 not taken.
|
97051958 | ha_statistic_increment(&System_status_var::ha_read_rnd_next_count); |
| 10957 | |||
| 10958 | /* | ||
| 10959 | Since order does not matter, the scan will occur go with natural index | ||
| 10960 | order. | ||
| 10961 | */ | ||
| 10962 |
1/2✓ Branch 0 taken 97051958 times.
✗ Branch 1 not taken.
|
97051958 | bool is_reverse_cf = m_key_descr_arr[active_index_pos()]->m_is_reverse_cf; |
| 10963 |
2/2✓ Branch 0 taken 23218 times.
✓ Branch 1 taken 97028740 times.
|
97051958 | if (!m_rnd_scan_started) { |
| 10964 |
1/2✓ Branch 0 taken 23218 times.
✗ Branch 1 not taken.
|
23218 | rc = index_read_intern(buf, !is_reverse_cf /* first */); |
| 10965 | 23218 | m_rnd_scan_started = true; | |
| 10966 | } else { | ||
| 10967 |
2/2✓ Branch 0 taken 24030636 times.
✓ Branch 1 taken 72998104 times.
|
97028740 | if (is_reverse_cf) { |
| 10968 |
1/2✓ Branch 0 taken 24030636 times.
✗ Branch 1 not taken.
|
24030636 | rc = index_next_with_direction_intern(buf, false, false); |
| 10969 | } else { | ||
| 10970 |
1/2✓ Branch 0 taken 72998104 times.
✗ Branch 1 not taken.
|
72998104 | rc = index_next_with_direction_intern(buf, true, false); |
| 10971 | } | ||
| 10972 | } | ||
| 10973 | |||
| 10974 |
1/2✓ Branch 0 taken 97051958 times.
✗ Branch 1 not taken.
|
97051958 | DBUG_RETURN(rc); |
| 10975 | } | ||
| 10976 | |||
| 10977 | 115118 | int ha_rocksdb::rnd_end() { | |
| 10978 |
1/2✓ Branch 0 taken 115118 times.
✗ Branch 1 not taken.
|
115118 | DBUG_ENTER_FUNC(); |
| 10979 |
2/4✓ Branch 0 taken 115118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 115118 times.
✗ Branch 3 not taken.
|
230236 | DBUG_RETURN(index_end()); |
| 10980 | } | ||
| 10981 | |||
| 10982 | 503807 | void ha_rocksdb::build_decoder() { | |
| 10983 | 503807 | m_converter->setup_field_decoders(table->read_set, active_index, | |
| 10984 | 503807 | m_keyread_only, | |
| 10985 | 503807 | m_lock_rows == RDB_LOCK_WRITE); | |
| 10986 | 503807 | } | |
| 10987 | |||
| 10988 | 186653103 | void ha_rocksdb::check_build_decoder() { | |
| 10989 |
2/2✓ Branch 0 taken 503807 times.
✓ Branch 1 taken 186149296 times.
|
186653103 | if (m_need_build_decoder) { |
| 10990 | 503807 | build_decoder(); | |
| 10991 | 503807 | m_need_build_decoder = false; | |
| 10992 | } | ||
| 10993 | 186653103 | } | |
| 10994 | |||
| 10995 | /** | ||
| 10996 | @return | ||
| 10997 | HA_EXIT_SUCCESS OK | ||
| 10998 | other HA_ERR error code (can be SE-specific) | ||
| 10999 | */ | ||
| 11000 | 504058 | int ha_rocksdb::index_init(uint idx, bool sorted) { | |
| 11001 |
1/2✓ Branch 0 taken 504058 times.
✗ Branch 1 not taken.
|
504058 | DBUG_ENTER_FUNC(); |
| 11002 | |||
| 11003 | 504058 | m_need_build_decoder = true; | |
| 11004 | 504058 | active_index = idx; | |
| 11005 | |||
| 11006 |
1/2✓ Branch 0 taken 504058 times.
✗ Branch 1 not taken.
|
504058 | THD *thd = ha_thd(); |
| 11007 |
3/6✓ Branch 0 taken 504058 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 504058 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 504058 times.
|
504058 | if (thd && thd->killed) { |
| 11008 | ✗ | DBUG_RETURN(HA_ERR_QUERY_INTERRUPTED); | |
| 11009 | } | ||
| 11010 | |||
| 11011 |
1/2✓ Branch 0 taken 504058 times.
✗ Branch 1 not taken.
|
504058 | Rdb_transaction *const tx = get_or_create_tx(thd); |
| 11012 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 504058 times.
|
504058 | assert(tx != nullptr); |
| 11013 | |||
| 11014 | 504058 | active_index = idx; | |
| 11015 |
6/6✓ Branch 0 taken 71471 times.
✓ Branch 1 taken 432587 times.
✓ Branch 2 taken 756 times.
✓ Branch 3 taken 70715 times.
✓ Branch 4 taken 756 times.
✓ Branch 5 taken 503302 times.
|
575529 | if (idx != table->s->primary_key && |
| 11016 | 71471 | m_key_descr_arr[idx]->is_partial_index()) { | |
| 11017 | 756 | m_iterator.reset( | |
| 11018 |
1/2✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
|
756 | new Rdb_iterator_partial(thd, m_key_descr_arr[active_index_pos()], |
| 11019 |
2/4✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 756 times.
✗ Branch 3 not taken.
|
756 | m_pk_descr, m_tbl_def, table)); |
| 11020 | } else { | ||
| 11021 | 503302 | m_iterator.reset(new Rdb_iterator_base( | |
| 11022 |
3/6✓ Branch 0 taken 503302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 503302 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 503302 times.
✗ Branch 5 not taken.
|
503302 | thd, m_key_descr_arr[active_index_pos()], m_pk_descr, m_tbl_def)); |
| 11023 | } | ||
| 11024 | |||
| 11025 | // If m_lock_rows is not RDB_LOCK_NONE then we will be doing a get_for_update | ||
| 11026 | // when accessing the index, so don't acquire the snapshot right away. | ||
| 11027 | // Otherwise acquire the snapshot immediately. | ||
| 11028 |
1/2✓ Branch 0 taken 504058 times.
✗ Branch 1 not taken.
|
504058 | tx->acquire_snapshot(m_lock_rows == RDB_LOCK_NONE); |
| 11029 | |||
| 11030 |
1/2✓ Branch 0 taken 504058 times.
✗ Branch 1 not taken.
|
504058 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11031 | } | ||
| 11032 | |||
| 11033 | /** | ||
| 11034 | @return | ||
| 11035 | HA_EXIT_SUCCESS OK | ||
| 11036 | */ | ||
| 11037 | 503445 | int ha_rocksdb::index_end() { | |
| 11038 |
1/2✓ Branch 0 taken 503445 times.
✗ Branch 1 not taken.
|
503445 | DBUG_ENTER_FUNC(); |
| 11039 | |||
| 11040 | 503445 | m_need_build_decoder = false; | |
| 11041 | |||
| 11042 | 503445 | m_iterator = nullptr; | |
| 11043 | |||
| 11044 | 503445 | active_index = MAX_KEY; | |
| 11045 | 503445 | in_range_check_pushed_down = false; | |
| 11046 | |||
| 11047 |
1/2✓ Branch 0 taken 503445 times.
✗ Branch 1 not taken.
|
503445 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11048 | } | ||
| 11049 | |||
| 11050 | /** | ||
| 11051 | Called by the partition manager for truncating tables. | ||
| 11052 | |||
| 11053 | @return | ||
| 11054 | HA_EXIT_SUCCESS OK | ||
| 11055 | other HA_ERR error code (can be SE-specific) | ||
| 11056 | */ | ||
| 11057 | 276 | int ha_rocksdb::truncate(dd::Table *table_def) { | |
| 11058 |
1/2✓ Branch 0 taken 276 times.
✗ Branch 1 not taken.
|
276 | DBUG_ENTER_FUNC(); |
| 11059 | |||
| 11060 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 276 times.
|
276 | assert(m_tbl_def != nullptr); |
| 11061 | |||
| 11062 | // Reset auto_increment_value to 1 if auto-increment feature is enabled | ||
| 11063 | // By default, the starting valid value for auto_increment_value is 1 | ||
| 11064 |
5/8✓ Branch 0 taken 276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 222 times.
✓ Branch 4 taken 276 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 276 times.
✗ Branch 7 not taken.
|
276 | DBUG_RETURN(truncate_table( |
| 11065 | m_tbl_def, "" /* actual_user_table_name */, table, | ||
| 11066 | table->found_next_number_field ? 1 : 0 /* auto_increment_value */, | ||
| 11067 | table_def)); | ||
| 11068 | } | ||
| 11069 | |||
| 11070 | 3995526 | int ha_rocksdb::reset() { | |
| 11071 |
1/2✓ Branch 0 taken 3995760 times.
✗ Branch 1 not taken.
|
3995526 | DBUG_ENTER_FUNC(); |
| 11072 | |||
| 11073 | /* Free blob data */ | ||
| 11074 |
1/2✓ Branch 0 taken 3995597 times.
✗ Branch 1 not taken.
|
3995760 | m_retrieved_record.Reset(); |
| 11075 |
1/2✓ Branch 0 taken 3995673 times.
✗ Branch 1 not taken.
|
3995597 | m_dup_key_retrieved_record.Reset(); |
| 11076 |
1/2✓ Branch 0 taken 3995427 times.
✗ Branch 1 not taken.
|
3995673 | release_blob_buffer(); |
| 11077 | 3995427 | m_iterator.reset(nullptr); | |
| 11078 | 3995797 | m_pk_iterator.reset(nullptr); | |
| 11079 |
1/2✓ Branch 0 taken 3995723 times.
✗ Branch 1 not taken.
|
3995816 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11080 | } | ||
| 11081 | |||
| 11082 | /* | ||
| 11083 | Delete the row we've last read. The row is also passed as parameter. | ||
| 11084 | |||
| 11085 | @detail | ||
| 11086 | The caller guarantees table buf points to the row that was just read. | ||
| 11087 | The row is either table->record[0] or table->record[1]. | ||
| 11088 | (Check out InnoDB: row_update_for_mysql() has "UT_NOT_USED(mysql_rec)" | ||
| 11089 | |||
| 11090 | @return | ||
| 11091 | HA_EXIT_SUCCESS OK | ||
| 11092 | other HA_ERR error code (can be SE-specific) | ||
| 11093 | */ | ||
| 11094 | 240972 | int ha_rocksdb::delete_row(const uchar *const buf) { | |
| 11095 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | DBUG_ENTER_FUNC(); |
| 11096 | |||
| 11097 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240972 times.
|
240972 | assert(buf != nullptr); |
| 11098 | |||
| 11099 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | ha_statistic_increment(&System_status_var::ha_delete_count); |
| 11100 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | set_last_rowkey(buf); |
| 11101 | |||
| 11102 | 240972 | rocksdb::Slice key_slice(m_last_rowkey.ptr(), m_last_rowkey.length()); | |
| 11103 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | Rdb_transaction *const tx = get_or_create_tx(table->in_use); |
| 11104 | |||
| 11105 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | const uint index = pk_index(table, m_tbl_def); |
| 11106 | rocksdb::Status s = | ||
| 11107 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | delete_or_singledelete(index, tx, m_pk_descr->get_cf(), key_slice); |
| 11108 |
2/4✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 240972 times.
|
240972 | if (!s.ok()) { |
| 11109 | ✗ | DBUG_RETURN(tx->set_status_error(table->in_use, s, *m_pk_descr, m_tbl_def)); | |
| 11110 | } | ||
| 11111 | |||
| 11112 | 240972 | longlong hidden_pk_id = 0; | |
| 11113 |
7/8✓ Branch 0 taken 215319 times.
✓ Branch 1 taken 25653 times.
✓ Branch 2 taken 215319 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3291 times.
✓ Branch 5 taken 212028 times.
✓ Branch 6 taken 3291 times.
✓ Branch 7 taken 237681 times.
|
240972 | if (m_tbl_def->m_key_count > 1 && has_hidden_pk(table)) { |
| 11114 |
1/2✓ Branch 0 taken 3291 times.
✗ Branch 1 not taken.
|
3291 | int err = read_hidden_pk_id_from_rowkey(&hidden_pk_id); |
| 11115 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3291 times.
|
3291 | if (err) { |
| 11116 | ✗ | DBUG_RETURN(err); | |
| 11117 | } | ||
| 11118 | } | ||
| 11119 | |||
| 11120 | // Delete the record for every secondary index | ||
| 11121 |
2/2✓ Branch 0 taken 456750 times.
✓ Branch 1 taken 240972 times.
|
697722 | for (uint i = 0; i < m_tbl_def->m_key_count; i++) { |
| 11122 |
3/4✓ Branch 0 taken 456750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 215778 times.
✓ Branch 3 taken 240972 times.
|
456750 | if (!is_pk(i, table, m_tbl_def)) { |
| 11123 | int packed_size; | ||
| 11124 | 215778 | const Rdb_key_def &kd = *m_key_descr_arr[i]; | |
| 11125 | |||
| 11126 | // The unique key should be locked so that behavior is | ||
| 11127 | // similar to InnoDB and reduce conflicts. The key | ||
| 11128 | // used for locking does not include the extended fields. | ||
| 11129 | 215778 | const KEY *key_info = &table->key_info[i]; | |
| 11130 |
2/2✓ Branch 0 taken 1101 times.
✓ Branch 1 taken 214677 times.
|
215778 | if (key_info->flags & HA_NOSAME) { |
| 11131 | 1101 | uint user_defined_key_parts = key_info->user_defined_key_parts; | |
| 11132 | 1101 | uint n_null_fields = 0; | |
| 11133 | |||
| 11134 |
1/2✓ Branch 0 taken 1101 times.
✗ Branch 1 not taken.
|
1101 | packed_size = kd.pack_record(table, m_pack_buffer, buf, |
| 11135 | m_sk_packed_tuple, nullptr, false, 0, | ||
| 11136 | user_defined_key_parts, &n_null_fields); | ||
| 11137 | |||
| 11138 | // NULL fields are considered unique, so no lock is needed | ||
| 11139 |
1/2✓ Branch 0 taken 1101 times.
✗ Branch 1 not taken.
|
1101 | if (n_null_fields == 0) { |
| 11140 | rocksdb::Slice sk_slice( | ||
| 11141 | 1101 | reinterpret_cast<const char *>(m_sk_packed_tuple), packed_size); | |
| 11142 |
1/2✓ Branch 0 taken 1101 times.
✗ Branch 1 not taken.
|
1101 | const rocksdb::Status s = get_for_update(tx, kd, sk_slice); |
| 11143 |
2/4✓ Branch 0 taken 1101 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1101 times.
|
1101 | if (!s.ok()) { |
| 11144 | ✗ | DBUG_RETURN(tx->set_status_error(table->in_use, s, kd, m_tbl_def)); | |
| 11145 | } | ||
| 11146 |
1/2✓ Branch 0 taken 1101 times.
✗ Branch 1 not taken.
|
1101 | } |
| 11147 | } | ||
| 11148 | |||
| 11149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 215778 times.
|
215778 | if (kd.is_partial_index()) { |
| 11150 | // Obtain shared lock on prefix. | ||
| 11151 | ✗ | int rc = acquire_prefix_lock(kd, tx, buf); | |
| 11152 | ✗ | if (rc) DBUG_RETURN(rc); | |
| 11153 | } | ||
| 11154 | |||
| 11155 |
1/2✓ Branch 0 taken 215778 times.
✗ Branch 1 not taken.
|
215778 | packed_size = kd.pack_record(table, m_pack_buffer, buf, m_sk_packed_tuple, |
| 11156 | nullptr, false, hidden_pk_id); | ||
| 11157 | rocksdb::Slice secondary_key_slice( | ||
| 11158 | 215778 | reinterpret_cast<const char *>(m_sk_packed_tuple), packed_size); | |
| 11159 |
2/4✓ Branch 0 taken 215778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 215778 times.
✗ Branch 3 not taken.
|
215778 | tx->get_indexed_write_batch()->SingleDelete(kd.get_cf(), |
| 11160 | secondary_key_slice); | ||
| 11161 | } | ||
| 11162 | } | ||
| 11163 | |||
| 11164 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | tx->log_table_write_op(m_tbl_def); |
| 11165 | |||
| 11166 |
2/4✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 240972 times.
|
240972 | if (do_bulk_commit(tx)) { |
| 11167 | ✗ | DBUG_RETURN(HA_ERR_ROCKSDB_BULK_LOAD); | |
| 11168 | } | ||
| 11169 | |||
| 11170 | // Not protected by ddl_manger lock for performance | ||
| 11171 | // reasons. This is an estimate value anyway. | ||
| 11172 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | dec_table_n_rows(); |
| 11173 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | update_table_stats_if_needed(); |
| 11174 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | update_row_stats(ROWS_DELETED); |
| 11175 | |||
| 11176 |
1/2✓ Branch 0 taken 240972 times.
✗ Branch 1 not taken.
|
240972 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11177 | 240972 | } | |
| 11178 | |||
| 11179 | 384400 | rocksdb::Status ha_rocksdb::delete_or_singledelete( | |
| 11180 | uint index, Rdb_transaction *const tx, | ||
| 11181 | rocksdb::ColumnFamilyHandle *const column_family, | ||
| 11182 | const rocksdb::Slice &key) { | ||
| 11183 | 384400 | const bool assume_tracked = can_assume_tracked(ha_thd()); | |
| 11184 |
2/2✓ Branch 0 taken 104375 times.
✓ Branch 1 taken 280025 times.
|
384400 | if (can_use_single_delete(index)) { |
| 11185 | 104375 | return tx->single_delete(column_family, key, assume_tracked); | |
| 11186 | } | ||
| 11187 | 280025 | return tx->delete_key(column_family, key, assume_tracked); | |
| 11188 | } | ||
| 11189 | |||
| 11190 | 249 | int ha_rocksdb::adjust_handler_stats_table_scan(ha_statistics *ha_stats, | |
| 11191 | Rdb_tbl_def *tbl_def) { | ||
| 11192 |
1/2✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
|
249 | DBUG_ENTER_FUNC(); |
| 11193 | |||
| 11194 | 249 | bool should_recalc_stats = false; | |
| 11195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (static_cast<longlong>(ha_stats->data_file_length) < 0) { |
| 11196 | ✗ | ha_stats->data_file_length = 0; | |
| 11197 | ✗ | should_recalc_stats = true; | |
| 11198 | } | ||
| 11199 | |||
| 11200 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (static_cast<longlong>(ha_stats->index_file_length) < 0) { |
| 11201 | ✗ | ha_stats->index_file_length = 0; | |
| 11202 | ✗ | should_recalc_stats = true; | |
| 11203 | } | ||
| 11204 | |||
| 11205 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (static_cast<longlong>(ha_stats->records) < 0) { |
| 11206 | ✗ | ha_stats->records = 1; | |
| 11207 | ✗ | should_recalc_stats = true; | |
| 11208 | } | ||
| 11209 | |||
| 11210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (should_recalc_stats) { |
| 11211 | // If any of the stats is corrupt, add the table to the index stats | ||
| 11212 | // recalc queue. | ||
| 11213 | ✗ | rdb_is_thread.add_index_stats_request(tbl_def->full_tablename()); | |
| 11214 | } | ||
| 11215 |
1/2✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
|
249 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11216 | } | ||
| 11217 | |||
| 11218 | 463264 | int ha_rocksdb::update_stats(ha_statistics *ha_stats, Rdb_tbl_def *tbl_def, | |
| 11219 | bool from_handler) { | ||
| 11220 | /* | ||
| 11221 | Test only to simulate corrupted stats | ||
| 11222 | */ | ||
| 11223 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 463262 times.
|
463264 | DBUG_EXECUTE_IF("myrocks_simulate_negative_stats", { |
| 11224 | auto pk_def = tbl_def->get_pk_def(); | ||
| 11225 | pk_def->m_stats.m_actual_disk_size = -pk_def->m_stats.m_actual_disk_size; | ||
| 11226 | }); | ||
| 11227 | |||
| 11228 | 463265 | rocksdb_get_stats(ha_stats, tbl_def); | |
| 11229 |
2/2✓ Branch 0 taken 249 times.
✓ Branch 1 taken 463015 times.
|
463264 | if (rocksdb_table_stats_use_table_scan) { |
| 11230 | 249 | int ret = adjust_handler_stats_table_scan(ha_stats, tbl_def); | |
| 11231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (ret != HA_EXIT_SUCCESS) { |
| 11232 | ✗ | return ret; | |
| 11233 | } | ||
| 11234 | } else { | ||
| 11235 | 463015 | int ret = adjust_handler_stats_sst_and_memtable(ha_stats, tbl_def); | |
| 11236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 463014 times.
|
463014 | if (ret != HA_EXIT_SUCCESS) { |
| 11237 | ✗ | return ret; | |
| 11238 | } | ||
| 11239 | } | ||
| 11240 | |||
| 11241 |
2/2✓ Branch 0 taken 44513 times.
✓ Branch 1 taken 418750 times.
|
463263 | if (rocksdb_debug_optimizer_n_rows > 0) { |
| 11242 | 44513 | ha_stats->records = rocksdb_debug_optimizer_n_rows; | |
| 11243 | } | ||
| 11244 | |||
| 11245 |
2/2✓ Branch 0 taken 408581 times.
✓ Branch 1 taken 54682 times.
|
463263 | if (ha_stats->records != 0) { |
| 11246 | 408581 | ha_stats->mean_rec_length = ha_stats->data_file_length / ha_stats->records; | |
| 11247 | } | ||
| 11248 | |||
| 11249 | // Skip the rest if we are called from ha_rocksdb::info which will perform | ||
| 11250 | // following updates based on flag. Alawys update auto_inc_val is expensive | ||
| 11251 | // from ha_rocksdb::info as it involves a DBImpl::Get so we don't want to | ||
| 11252 | // do that in steady state. When called from rocksdb_get_table_statistics | ||
| 11253 | // it is fine as it is much less frequent | ||
| 11254 |
2/2✓ Branch 0 taken 396 times.
✓ Branch 1 taken 462867 times.
|
463263 | if (!from_handler) { |
| 11255 | // HA_STATUS_TIME | ||
| 11256 | 396 | ha_stats->update_time = tbl_def->m_update_time; | |
| 11257 | |||
| 11258 | // HA_STATUS_AUTO | ||
| 11259 | // Because we haven't opened the table yet, we need to load auto incr | ||
| 11260 | // value here. Note we won't know if the table actually has auto incr | ||
| 11261 | // without opening the table, so there is a corner case it'll end up | ||
| 11262 | // being NULL if the table has just been created and haven't been | ||
| 11263 | // opened yet - InnoDB has the same issue | ||
| 11264 |
2/2✓ Branch 0 taken 257 times.
✓ Branch 1 taken 139 times.
|
396 | if (tbl_def->m_auto_incr_val == 0) { |
| 11265 | // Unfortunately in this case we don't know if we actually have auto | ||
| 11266 | // increment without opening the table, so we'd have to load the value | ||
| 11267 | // always even if the table doesn't have auto increment | ||
| 11268 |
1/2✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
|
257 | const GL_INDEX_ID &gl_index_id = tbl_def->get_autoincr_gl_index_id(); |
| 11269 | 514 | if (!dict_manager.get_dict_manager_selector_const(gl_index_id.cf_id) | |
| 11270 |
4/6✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 203 times.
✓ Branch 5 taken 54 times.
|
257 | ->get_auto_incr_val(gl_index_id, |
| 11271 | &ha_stats->auto_increment_value)) { | ||
| 11272 | 203 | ha_stats->auto_increment_value = 0; | |
| 11273 | } | ||
| 11274 | } else { | ||
| 11275 | 139 | ha_stats->auto_increment_value = tbl_def->m_auto_incr_val; | |
| 11276 | } | ||
| 11277 | } | ||
| 11278 | |||
| 11279 | 463263 | return HA_EXIT_SUCCESS; | |
| 11280 | } | ||
| 11281 | |||
| 11282 | /** | ||
| 11283 | @return | ||
| 11284 | HA_EXIT_SUCCESS OK | ||
| 11285 | HA_EXIT_FAILURE Error | ||
| 11286 | */ | ||
| 11287 | 469687 | int ha_rocksdb::info(uint flag) { | |
| 11288 |
1/2✓ Branch 0 taken 469693 times.
✗ Branch 1 not taken.
|
469687 | DBUG_ENTER_FUNC(); |
| 11289 | |||
| 11290 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 469693 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
469693 | if (!table) DBUG_RETURN(HA_EXIT_FAILURE); |
| 11291 | |||
| 11292 |
2/2✓ Branch 0 taken 462868 times.
✓ Branch 1 taken 6825 times.
|
469693 | if (flag & HA_STATUS_VARIABLE) { |
| 11293 |
1/2✓ Branch 0 taken 462866 times.
✗ Branch 1 not taken.
|
462868 | int ret = update_stats(&stats, m_tbl_def, /* from_handler */ true); |
| 11294 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 462866 times.
|
462866 | if (ret != HA_EXIT_SUCCESS) { |
| 11295 | ✗ | return ret; | |
| 11296 | } | ||
| 11297 | } | ||
| 11298 | |||
| 11299 |
2/2✓ Branch 0 taken 464491 times.
✓ Branch 1 taken 5200 times.
|
469691 | if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST)) { |
| 11300 | 464491 | ref_length = m_pk_descr->max_storage_fmt_length(); | |
| 11301 | |||
| 11302 |
2/2✓ Branch 0 taken 760882 times.
✓ Branch 1 taken 464487 times.
|
1225369 | for (uint i = 0; i < m_tbl_def->m_key_count; i++) { |
| 11303 |
3/4✓ Branch 0 taken 760881 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39527 times.
✓ Branch 3 taken 721354 times.
|
760882 | if (is_hidden_pk(i, table, m_tbl_def)) { |
| 11304 | 39527 | continue; | |
| 11305 | } | ||
| 11306 | 721354 | KEY *const k = &table->key_info[i]; | |
| 11307 | 721354 | auto records = stats.records; | |
| 11308 |
2/2✓ Branch 0 taken 1613730 times.
✓ Branch 1 taken 721353 times.
|
2335083 | for (uint j = 0; j < k->actual_key_parts; j++) { |
| 11309 | 1613730 | const Rdb_index_stats &k_stats = m_key_descr_arr[i]->m_stats; | |
| 11310 | 1613728 | rec_per_key_t x = REC_PER_KEY_UNKNOWN; | |
| 11311 | |||
| 11312 | // Doesn't make sense to calculate cardinality if there are no records | ||
| 11313 |
2/2✓ Branch 0 taken 1457619 times.
✓ Branch 1 taken 156109 times.
|
1613728 | if (records > 0) { |
| 11314 |
3/4✓ Branch 0 taken 1457619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 864225 times.
✓ Branch 3 taken 593394 times.
|
2915238 | if (k_stats.m_distinct_keys_per_prefix.size() > j && |
| 11315 |
2/2✓ Branch 0 taken 864225 times.
✓ Branch 1 taken 593394 times.
|
1457619 | k_stats.m_distinct_keys_per_prefix[j] > 0) { |
| 11316 | 1728450 | x = (rec_per_key_t)k_stats.m_rows / | |
| 11317 | 864225 | k_stats.m_distinct_keys_per_prefix[j]; | |
| 11318 | |||
| 11319 | /* | ||
| 11320 | If the number of rows is less than the number of prefixes (due to | ||
| 11321 | sampling), the average number of rows with the same prefix is 1. | ||
| 11322 | */ | ||
| 11323 |
2/2✓ Branch 0 taken 814 times.
✓ Branch 1 taken 863411 times.
|
864225 | if (x < 1) { |
| 11324 | 814 | x = 1; | |
| 11325 | } | ||
| 11326 | } | ||
| 11327 | |||
| 11328 |
4/4✓ Branch 0 taken 593394 times.
✓ Branch 1 taken 864225 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 593376 times.
|
1457619 | if ((x == REC_PER_KEY_UNKNOWN && |
| 11329 | 864243 | rocksdb_debug_optimizer_no_zero_cardinality) || | |
| 11330 |
2/2✓ Branch 0 taken 132267 times.
✓ Branch 1 taken 731976 times.
|
864243 | rocksdb_debug_optimizer_n_rows > 0) { |
| 11331 | // Fake cardinality implementation. For example, (idx1, idx2, idx3) | ||
| 11332 | // index | ||
| 11333 | // will have rec_per_key for (idx1)=4, (idx1,2)=2, and (idx1,2,3)=1. | ||
| 11334 | // rec_per_key for the whole index is 1, and multiplied by 2^n if | ||
| 11335 | // n suffix columns of the index are not used. | ||
| 11336 |
2/2✓ Branch 0 taken 714987 times.
✓ Branch 1 taken 10656 times.
|
725643 | if (rocksdb_debug_cardinality_multiplier == 2) { |
| 11337 | 714987 | x = 1 << (k->actual_key_parts - j - 1); | |
| 11338 | } else { | ||
| 11339 | 10656 | x = 1; | |
| 11340 |
2/2✓ Branch 0 taken 15984 times.
✓ Branch 1 taken 10656 times.
|
26640 | for (uint kp = 1; kp <= k->actual_key_parts - j - 1; kp++) { |
| 11341 | 15984 | x *= rocksdb_debug_cardinality_multiplier; | |
| 11342 | } | ||
| 11343 | } | ||
| 11344 | } | ||
| 11345 | |||
| 11346 |
2/2✓ Branch 0 taken 11288 times.
✓ Branch 1 taken 1446331 times.
|
1457619 | if (x > records) x = records; |
| 11347 | } | ||
| 11348 | |||
| 11349 | // 1 <= x <= records, or x = REC_PER_KEY_UNKNOWN | ||
| 11350 | 1613728 | k->set_records_per_key(j, x); | |
| 11351 | } | ||
| 11352 | } | ||
| 11353 | |||
| 11354 |
1/2✓ Branch 0 taken 464488 times.
✗ Branch 1 not taken.
|
464487 | stats.create_time = m_tbl_def->get_create_time(); |
| 11355 | } | ||
| 11356 | |||
| 11357 |
2/2✓ Branch 0 taken 2752 times.
✓ Branch 1 taken 466936 times.
|
469688 | if (flag & HA_STATUS_TIME) { |
| 11358 | 2752 | stats.update_time = m_tbl_def->m_update_time; | |
| 11359 | } | ||
| 11360 | |||
| 11361 |
2/2✓ Branch 0 taken 3071 times.
✓ Branch 1 taken 466617 times.
|
469688 | if (flag & HA_STATUS_ERRKEY) { |
| 11362 | /* | ||
| 11363 | Currently we support only primary keys so we know which key had a | ||
| 11364 | uniqueness violation. | ||
| 11365 | */ | ||
| 11366 | 3071 | errkey = m_dupp_errkey; | |
| 11367 | } | ||
| 11368 | |||
| 11369 |
2/2✓ Branch 0 taken 2922 times.
✓ Branch 1 taken 466766 times.
|
469688 | if (flag & HA_STATUS_AUTO) { |
| 11370 | 2922 | stats.auto_increment_value = m_tbl_def->m_auto_incr_val; | |
| 11371 | } | ||
| 11372 | |||
| 11373 |
1/2✓ Branch 0 taken 469691 times.
✗ Branch 1 not taken.
|
469688 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11374 | } | ||
| 11375 | |||
| 11376 | 192429 | void ha_rocksdb::position(const uchar *const record) { | |
| 11377 |
1/2✓ Branch 0 taken 192429 times.
✗ Branch 1 not taken.
|
192429 | DBUG_ENTER_FUNC(); |
| 11378 | |||
| 11379 | 192429 | longlong hidden_pk_id = 0; | |
| 11380 |
6/10✓ Branch 0 taken 192429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71905 times.
✓ Branch 3 taken 120524 times.
✓ Branch 4 taken 71905 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 71905 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 192429 times.
|
192429 | if (has_hidden_pk(table) && read_hidden_pk_id_from_rowkey(&hidden_pk_id)) { |
| 11381 | ✗ | assert(false); // should never reach here | |
| 11382 | } | ||
| 11383 | |||
| 11384 | /* | ||
| 11385 | Get packed primary key value from the record. | ||
| 11386 | |||
| 11387 | (Note: m_last_rowkey has the packed PK of last-read-row, which allows to | ||
| 11388 | handle most cases, but there is an exception to this: when slave applies | ||
| 11389 | RBR events, it fills the record and then calls position(); rnd_pos()) | ||
| 11390 | |||
| 11391 | Also note that we *can* rely on PK column values being available. This is | ||
| 11392 | because table_flags() includes HA_PRIMARY_KEY_REQUIRED_FOR_POSITION bit. | ||
| 11393 | When that is true, table->prepare_for_position() adds PK columns into the | ||
| 11394 | read set (this may potentially disable index-only access when PK column | ||
| 11395 | cannot be restored from its mem-comparable form in the secondary indexes). | ||
| 11396 | */ | ||
| 11397 | 192429 | const uint packed_size = m_pk_descr->pack_record( | |
| 11398 |
1/2✓ Branch 0 taken 192429 times.
✗ Branch 1 not taken.
|
192429 | table, m_pack_buffer, record, ref, nullptr, false, hidden_pk_id); |
| 11399 | |||
| 11400 | /* | ||
| 11401 | It could be that mem-comparable form of PK occupies less than ref_length | ||
| 11402 | bytes. Fill the remainder with zeros. | ||
| 11403 | */ | ||
| 11404 |
2/2✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 191174 times.
|
192429 | if (ref_length > packed_size) { |
| 11405 | 1255 | memset(ref + packed_size, 0, ref_length - packed_size); | |
| 11406 | } | ||
| 11407 | |||
| 11408 |
1/2✓ Branch 0 taken 192429 times.
✗ Branch 1 not taken.
|
384858 | DBUG_VOID_RETURN; |
| 11409 | } | ||
| 11410 | |||
| 11411 | /** | ||
| 11412 | @return | ||
| 11413 | HA_EXIT_SUCCESS OK | ||
| 11414 | other HA_ERR error code (can be SE-specific) | ||
| 11415 | */ | ||
| 11416 | 122275 | int ha_rocksdb::rnd_pos(uchar *const buf, uchar *const pos) { | |
| 11417 |
1/2✓ Branch 0 taken 122275 times.
✗ Branch 1 not taken.
|
122275 | DBUG_ENTER_FUNC(); |
| 11418 | |||
| 11419 |
1/2✓ Branch 0 taken 122275 times.
✗ Branch 1 not taken.
|
122275 | check_build_decoder(); |
| 11420 | |||
| 11421 | int rc; | ||
| 11422 | size_t len; | ||
| 11423 | |||
| 11424 |
1/2✓ Branch 0 taken 122275 times.
✗ Branch 1 not taken.
|
122275 | ha_statistic_increment(&System_status_var::ha_read_rnd_count); |
| 11425 |
1/2✓ Branch 0 taken 122275 times.
✗ Branch 1 not taken.
|
244550 | len = m_pk_descr->key_length(table, |
| 11426 | 122275 | rocksdb::Slice((const char *)pos, ref_length)); | |
| 11427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 122275 times.
|
122275 | if (len == size_t(-1)) { |
| 11428 | ✗ | DBUG_RETURN(HA_ERR_ROCKSDB_CORRUPT_DATA); /* Data corruption? */ | |
| 11429 | } | ||
| 11430 | |||
| 11431 |
1/2✓ Branch 0 taken 122275 times.
✗ Branch 1 not taken.
|
122275 | rc = get_row_by_rowid(buf, pos, len); |
| 11432 | |||
| 11433 |
2/2✓ Branch 0 taken 122269 times.
✓ Branch 1 taken 6 times.
|
122275 | if (!rc) { |
| 11434 |
1/2✓ Branch 0 taken 122269 times.
✗ Branch 1 not taken.
|
122269 | update_row_stats(ROWS_READ); |
| 11435 | } | ||
| 11436 | |||
| 11437 |
1/2✓ Branch 0 taken 122275 times.
✗ Branch 1 not taken.
|
122275 | DBUG_RETURN(rc); |
| 11438 | } | ||
| 11439 | |||
| 11440 | /* | ||
| 11441 | @brief | ||
| 11442 | Calculate (if needed) the bitmap of indexes that are modified by the | ||
| 11443 | current query | ||
| 11444 | |||
| 11445 | @detail | ||
| 11446 | The calculation done by checking index definitions against the | ||
| 11447 | table->write_set | ||
| 11448 | column bitmap. | ||
| 11449 | */ | ||
| 11450 | |||
| 11451 | 265727 | void ha_rocksdb::calc_updated_indexes() { | |
| 11452 | 265727 | m_update_scope.clear_all(); | |
| 11453 | |||
| 11454 |
2/2✓ Branch 0 taken 534969 times.
✓ Branch 1 taken 265727 times.
|
800696 | for (uint keynr = 0; keynr < table->s->keys; keynr++) { |
| 11455 | 534969 | const Rdb_key_def &kd = *m_key_descr_arr[keynr]; | |
| 11456 | /* Walk over all key parts, including the "extended key" suffix */ | ||
| 11457 | 534969 | const uint key_parts = kd.get_key_parts(); | |
| 11458 |
2/2✓ Branch 0 taken 535569 times.
✓ Branch 1 taken 544 times.
|
536113 | for (uint kp = 0; kp < key_parts; kp++) { |
| 11459 |
6/6✓ Branch 0 taken 85917 times.
✓ Branch 1 taken 449652 times.
✓ Branch 2 taken 600 times.
✓ Branch 3 taken 85317 times.
✓ Branch 4 taken 600 times.
✓ Branch 5 taken 534969 times.
|
535569 | if (has_hidden_pk(table) && kp + 1 == key_parts) break; |
| 11460 | |||
| 11461 | 534969 | Field *const field = kd.get_table_field_for_part_no(table, kp); | |
| 11462 |
2/2✓ Branch 0 taken 533825 times.
✓ Branch 1 taken 1144 times.
|
534969 | if (bitmap_is_set(table->write_set, field->field_index())) { |
| 11463 | 533825 | m_update_scope.set_bit(keynr); | |
| 11464 | 533825 | break; | |
| 11465 | } | ||
| 11466 | } | ||
| 11467 | } | ||
| 11468 | 265727 | } | |
| 11469 | |||
| 11470 | /** | ||
| 11471 | Update an existing row | ||
| 11472 | @param[in] old_data nullptr for write, non-null for update | ||
| 11473 | @param[in] new_data non-null for write/update | ||
| 11474 | @return | ||
| 11475 | HA_EXIT_SUCCESS OK | ||
| 11476 | other HA_ERR error code (can be SE-specific) | ||
| 11477 | */ | ||
| 11478 | 265728 | int ha_rocksdb::update_row(const uchar *const old_data, uchar *const new_data) { | |
| 11479 |
1/2✓ Branch 0 taken 265728 times.
✗ Branch 1 not taken.
|
265728 | DBUG_ENTER_FUNC(); |
| 11480 | |||
| 11481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 265728 times.
|
265728 | assert(old_data != nullptr); |
| 11482 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 265728 times.
|
265728 | assert(new_data != nullptr); |
| 11483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 265728 times.
|
265728 | assert(m_lock_rows == RDB_LOCK_WRITE); |
| 11484 | /* | ||
| 11485 | old_data points to record we're updating. It is the same as the record | ||
| 11486 | we've just read (for multi-table UPDATE, too, because SQL layer will make | ||
| 11487 | an rnd_pos() call to re-read the record before calling update_row()) | ||
| 11488 | */ | ||
| 11489 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 265728 times.
|
265728 | assert(new_data == table->record[0]); |
| 11490 | |||
| 11491 |
1/2✓ Branch 0 taken 265728 times.
✗ Branch 1 not taken.
|
265728 | ha_statistic_increment(&System_status_var::ha_update_count); |
| 11492 |
2/4✓ Branch 0 taken 265728 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 265728 times.
✗ Branch 3 not taken.
|
265728 | const int rv = update_write_row(old_data, new_data, skip_unique_check()); |
| 11493 | |||
| 11494 |
2/2✓ Branch 0 taken 265662 times.
✓ Branch 1 taken 66 times.
|
265728 | if (rv == 0) { |
| 11495 |
1/2✓ Branch 0 taken 265662 times.
✗ Branch 1 not taken.
|
265662 | update_table_stats_if_needed(); |
| 11496 |
1/2✓ Branch 0 taken 265662 times.
✗ Branch 1 not taken.
|
265662 | update_row_stats(ROWS_UPDATED); |
| 11497 | } | ||
| 11498 | |||
| 11499 |
1/2✓ Branch 0 taken 265728 times.
✗ Branch 1 not taken.
|
265728 | DBUG_RETURN(rv); |
| 11500 | } | ||
| 11501 | |||
| 11502 | 70931408 | void ha_rocksdb::update_table_stats_if_needed() { | |
| 11503 |
1/2✓ Branch 0 taken 70991479 times.
✗ Branch 1 not taken.
|
70931408 | DBUG_ENTER_FUNC(); |
| 11504 | |||
| 11505 |
2/2✓ Branch 0 taken 70962379 times.
✓ Branch 1 taken 29100 times.
|
70991479 | if (!rocksdb_table_stats_use_table_scan) { |
| 11506 |
1/2✓ Branch 0 taken 70968791 times.
✗ Branch 1 not taken.
|
70962379 | DBUG_VOID_RETURN; |
| 11507 | } | ||
| 11508 | |||
| 11509 | /* | ||
| 11510 | InnoDB performs a similar operation to update counters during query | ||
| 11511 | processing. Because the changes in MyRocks are made to a write batch, | ||
| 11512 | it is possible for the table scan cardinality calculation to trigger | ||
| 11513 | before the transaction performing the update commits. Hence the | ||
| 11514 | cardinality scan might miss the keys for these pending transactions. | ||
| 11515 | */ | ||
| 11516 | 29100 | uint64 counter = m_tbl_def->m_tbl_stats.m_stat_modified_counter++; | |
| 11517 | 29100 | uint64 n_rows = m_tbl_def->m_tbl_stats.m_stat_n_rows; | |
| 11518 | |||
| 11519 | 59472 | if (counter > std::max(rocksdb_table_stats_recalc_threshold_count, | |
| 11520 |
2/2✓ Branch 0 taken 80 times.
✓ Branch 1 taken 30292 times.
|
30372 | static_cast<long long unsigned int>( |
| 11521 | 29100 | n_rows * rocksdb_table_stats_recalc_threshold_pct / | |
| 11522 | 100.0))) { | ||
| 11523 | // Add the table to the recalc queue | ||
| 11524 |
1/2✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
|
80 | rdb_is_thread.add_index_stats_request(m_tbl_def->full_tablename()); |
| 11525 | 80 | m_tbl_def->m_tbl_stats.m_stat_modified_counter = 0; | |
| 11526 | } | ||
| 11527 | |||
| 11528 |
1/2✓ Branch 0 taken 30372 times.
✗ Branch 1 not taken.
|
30372 | DBUG_VOID_RETURN; |
| 11529 | } | ||
| 11530 | |||
| 11531 | /* The following function was copied from ha_blackhole::store_lock: */ | ||
| 11532 | 3986011 | THR_LOCK_DATA **ha_rocksdb::store_lock(THD *const thd, THR_LOCK_DATA **to, | |
| 11533 | enum thr_lock_type lock_type) { | ||
| 11534 |
1/2✓ Branch 0 taken 3986209 times.
✗ Branch 1 not taken.
|
3986011 | DBUG_ENTER_FUNC(); |
| 11535 | |||
| 11536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3986209 times.
|
3986209 | assert(thd != nullptr); |
| 11537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3986209 times.
|
3986209 | assert(to != nullptr); |
| 11538 | |||
| 11539 |
1/2✓ Branch 0 taken 3986092 times.
✗ Branch 1 not taken.
|
3986209 | bool in_lock_tables = my_core::thd_in_lock_tables(thd); |
| 11540 | |||
| 11541 | /* First, make a decision about MyRocks's internal locking */ | ||
| 11542 |
2/2✓ Branch 0 taken 3831982 times.
✓ Branch 1 taken 154110 times.
|
3986092 | if (lock_type >= TL_WRITE_ALLOW_WRITE) { |
| 11543 | 3831982 | m_lock_rows = RDB_LOCK_WRITE; | |
| 11544 |
2/2✓ Branch 0 taken 201 times.
✓ Branch 1 taken 153909 times.
|
154110 | } else if (lock_type == TL_READ_WITH_SHARED_LOCKS) { |
| 11545 | 201 | m_lock_rows = RDB_LOCK_READ; | |
| 11546 |
2/2✓ Branch 0 taken 150018 times.
✓ Branch 1 taken 3891 times.
|
153909 | } else if (lock_type != TL_IGNORE) { |
| 11547 | 150018 | m_lock_rows = RDB_LOCK_NONE; | |
| 11548 |
3/4✓ Branch 0 taken 150018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 150006 times.
|
150018 | if (THDVAR(thd, lock_scanned_rows)) { |
| 11549 | /* | ||
| 11550 | The following logic was copied directly from | ||
| 11551 | ha_innobase::store_lock_with_x_type() in | ||
| 11552 | storage/innobase/handler/ha_innodb.cc and causes MyRocks to leave | ||
| 11553 | locks in place on rows that are in a table that is not being updated. | ||
| 11554 | */ | ||
| 11555 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | const uint sql_command = my_core::thd_sql_command(thd); |
| 11556 |
3/6✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
12 | if ((lock_type == TL_READ && in_lock_tables) || |
| 11557 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) || |
| 11558 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | lock_type == TL_READ_WITH_SHARED_LOCKS || |
| 11559 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | lock_type == TL_READ_NO_INSERT || |
| 11560 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | (lock_type != TL_IGNORE && sql_command != SQLCOM_SELECT)) { |
| 11561 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ulong tx_isolation = my_core::thd_tx_isolation(thd); |
| 11562 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | if (sql_command != SQLCOM_CHECKSUM && |
| 11563 |
4/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
|
6 | ((my_core::thd_test_options(thd, OPTION_BIN_LOG) && |
| 11564 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | tx_isolation > ISO_READ_COMMITTED) || |
| 11565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | tx_isolation == ISO_SERIALIZABLE || |
| 11566 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | (lock_type != TL_READ && lock_type != TL_READ_NO_INSERT) || |
| 11567 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | (sql_command != SQLCOM_INSERT_SELECT && |
| 11568 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | sql_command != SQLCOM_REPLACE_SELECT && |
| 11569 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | sql_command != SQLCOM_UPDATE && sql_command != SQLCOM_DELETE && |
| 11570 | sql_command != SQLCOM_CREATE_TABLE))) { | ||
| 11571 | 6 | m_lock_rows = RDB_LOCK_READ; | |
| 11572 | } | ||
| 11573 | } | ||
| 11574 | } | ||
| 11575 | } | ||
| 11576 | |||
| 11577 | /* Then, tell the SQL layer what kind of locking it should use: */ | ||
| 11578 |
3/4✓ Branch 0 taken 3982085 times.
✓ Branch 1 taken 4007 times.
✓ Branch 2 taken 3982173 times.
✗ Branch 3 not taken.
|
3986092 | if (lock_type != TL_IGNORE && m_db_lock.type == TL_UNLOCK) { |
| 11579 | /* | ||
| 11580 | Here is where we get into the guts of a row level lock. | ||
| 11581 | If TL_UNLOCK is set | ||
| 11582 | If we are not doing a LOCK TABLE or DISCARD/IMPORT | ||
| 11583 | TABLESPACE, then allow multiple writers | ||
| 11584 | */ | ||
| 11585 | |||
| 11586 |
1/2✓ Branch 0 taken 3831975 times.
✗ Branch 1 not taken.
|
3831967 | if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) && |
| 11587 |
8/10✓ Branch 0 taken 3831967 times.
✓ Branch 1 taken 150206 times.
✓ Branch 2 taken 3831680 times.
✓ Branch 3 taken 295 times.
✓ Branch 4 taken 3831584 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3831604 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3831616 times.
✓ Branch 9 taken 150461 times.
|
7814140 | !in_lock_tables && !my_core::thd_tablespace_op(thd)) { |
| 11588 | 3831616 | lock_type = TL_WRITE_ALLOW_WRITE; | |
| 11589 | } | ||
| 11590 | |||
| 11591 | /* | ||
| 11592 | In queries of type INSERT INTO t1 SELECT ... FROM t2 ... | ||
| 11593 | MySQL would use the lock TL_READ_NO_INSERT on t2, and that | ||
| 11594 | would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts | ||
| 11595 | to t2. Convert the lock to a normal read lock to allow | ||
| 11596 | concurrent inserts to t2. | ||
| 11597 | */ | ||
| 11598 | |||
| 11599 |
4/4✓ Branch 0 taken 3972 times.
✓ Branch 1 taken 3978105 times.
✓ Branch 2 taken 3947 times.
✓ Branch 3 taken 25 times.
|
3982077 | if (lock_type == TL_READ_NO_INSERT && !in_lock_tables) { |
| 11600 | 3947 | lock_type = TL_READ; | |
| 11601 | } | ||
| 11602 | |||
| 11603 | 3982077 | m_db_lock.type = lock_type; | |
| 11604 | } | ||
| 11605 | |||
| 11606 | 3985996 | m_locked_row_action = THR_WAIT; | |
| 11607 |
2/2✓ Branch 0 taken 3982155 times.
✓ Branch 1 taken 3841 times.
|
3985996 | if (lock_type != TL_IGNORE) { |
| 11608 | 3982155 | auto action = table->pos_in_table_list->lock_descriptor().action; | |
| 11609 |
3/3✓ Branch 0 taken 33 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 3981959 times.
|
3982031 | switch (action) { |
| 11610 | 33 | case THR_SKIP: | |
| 11611 | 33 | m_locked_row_action = THR_SKIP; | |
| 11612 | 33 | break; | |
| 11613 | 39 | case THR_NOWAIT: | |
| 11614 | 39 | m_locked_row_action = THR_NOWAIT; | |
| 11615 | 39 | break; | |
| 11616 | 3981959 | default: | |
| 11617 | 3981959 | break; | |
| 11618 | } | ||
| 11619 | } | ||
| 11620 | |||
| 11621 | 3985872 | *to++ = &m_db_lock; | |
| 11622 | |||
| 11623 |
1/2✓ Branch 0 taken 3986230 times.
✗ Branch 1 not taken.
|
3985872 | DBUG_RETURN(to); |
| 11624 | } | ||
| 11625 | |||
| 11626 | 3983358 | void ha_rocksdb::read_thd_vars(THD *const thd) { | |
| 11627 | 3983358 | m_store_row_debug_checksums = THDVAR(thd, store_row_debug_checksums); | |
| 11628 | 3983834 | m_converter->set_verify_row_debug_checksums( | |
| 11629 | 3983739 | THDVAR(thd, verify_row_debug_checksums)); | |
| 11630 | 3983594 | m_checksums_pct = THDVAR(thd, checksums_pct); | |
| 11631 | 3983831 | } | |
| 11632 | |||
| 11633 | /** | ||
| 11634 | @return | ||
| 11635 | HA_EXIT_SUCCESS OK | ||
| 11636 | other HA_ERR error code (cannot be SE-specific) | ||
| 11637 | */ | ||
| 11638 | 7967369 | int ha_rocksdb::external_lock(THD *const thd, int lock_type) { | |
| 11639 |
1/2✓ Branch 0 taken 7967604 times.
✗ Branch 1 not taken.
|
7967369 | DBUG_ENTER_FUNC(); |
| 11640 | |||
| 11641 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7967604 times.
|
7967604 | assert(thd != nullptr); |
| 11642 | |||
| 11643 | 7967604 | int res = HA_EXIT_SUCCESS; | |
| 11644 |
1/2✓ Branch 0 taken 7967427 times.
✗ Branch 1 not taken.
|
7967604 | int binlog_format = my_core::thd_binlog_format(thd); |
| 11645 |
2/4✓ Branch 0 taken 7967471 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7967500 times.
✗ Branch 3 not taken.
|
7967427 | bool unsafe_for_binlog = THDVAR(ha_thd(), unsafe_for_binlog); |
| 11646 |
6/6✓ Branch 0 taken 3808970 times.
✓ Branch 1 taken 24355 times.
✓ Branch 2 taken 3808598 times.
✓ Branch 3 taken 372 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 3808568 times.
|
3833325 | if (lock_type == F_WRLCK && !thd->rli_slave && !unsafe_for_binlog && |
| 11647 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
|
30 | binlog_format != BINLOG_FORMAT_ROW && |
| 11648 |
4/4✓ Branch 0 taken 3833325 times.
✓ Branch 1 taken 4134175 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 7967494 times.
|
11800825 | binlog_format != BINLOG_FORMAT_UNSPEC && |
| 11649 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | my_core::thd_binlog_filter_ok(thd)) { |
| 11650 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0)); |
| 11651 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(HA_ERR_UNSUPPORTED); |
| 11652 | } | ||
| 11653 | |||
| 11654 |
2/2✓ Branch 0 taken 3983825 times.
✓ Branch 1 taken 3983669 times.
|
7967494 | if (lock_type == F_UNLCK) { |
| 11655 |
1/2✓ Branch 0 taken 3983820 times.
✗ Branch 1 not taken.
|
3983825 | Rdb_transaction *const tx = get_tx_from_thd(thd); |
| 11656 | |||
| 11657 |
1/2✓ Branch 0 taken 3983821 times.
✗ Branch 1 not taken.
|
3983820 | if (tx) { |
| 11658 |
1/2✓ Branch 0 taken 3983810 times.
✗ Branch 1 not taken.
|
3983821 | tx->io_perf_end_and_record(&m_io_perf); |
| 11659 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3983810 times.
|
3983810 | assert(tx->m_n_mysql_tables_in_use > 0); |
| 11660 | 3983810 | tx->m_n_mysql_tables_in_use--; | |
| 11661 |
4/4✓ Branch 0 taken 3975488 times.
✓ Branch 1 taken 8322 times.
✓ Branch 2 taken 3554204 times.
✓ Branch 3 taken 429556 times.
|
7959248 | if (tx->m_n_mysql_tables_in_use == 0 && |
| 11662 |
3/4✓ Branch 0 taken 3975438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3554191 times.
✓ Branch 3 taken 421247 times.
|
3975488 | !my_core::thd_test_options(thd, |
| 11663 | OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { | ||
| 11664 | /* | ||
| 11665 | Do like InnoDB: when we get here, it's time to commit a | ||
| 11666 | single-statement transaction. | ||
| 11667 | |||
| 11668 | If the statement involved multiple tables, this code will be executed | ||
| 11669 | for each of them, but that's ok because non-first tx->commit() calls | ||
| 11670 | will be no-ops. | ||
| 11671 | */ | ||
| 11672 |
2/4✓ Branch 0 taken 3554079 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3554079 times.
|
3554204 | if (tx->commit_or_rollback()) { |
| 11673 | ✗ | res = HA_ERR_INTERNAL_ERROR; | |
| 11674 | } | ||
| 11675 | } | ||
| 11676 | } | ||
| 11677 | } else { | ||
| 11678 |
5/6✓ Branch 0 taken 3983454 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3983452 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 3983515 times.
|
7967197 | if (my_core::thd_tx_isolation(thd) < ISO_READ_COMMITTED || |
| 11679 |
2/4✓ Branch 0 taken 3983528 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3983561 times.
|
3983452 | my_core::thd_tx_isolation(thd) > ISO_REPEATABLE_READ) { |
| 11680 | 15 | my_error(ER_ISOLATION_MODE_NOT_SUPPORTED, MYF(0), | |
| 11681 |
2/4✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
15 | tx_isolation_names[my_core::thd_tx_isolation(thd)]); |
| 11682 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | DBUG_RETURN(HA_ERR_UNSUPPORTED); |
| 11683 | } | ||
| 11684 | /* | ||
| 11685 | It's nice to do the following on start of every statement. The problem | ||
| 11686 | is, handler->start_stmt() is not called for INSERTs. | ||
| 11687 | So, we put this code here. | ||
| 11688 | */ | ||
| 11689 |
1/2✓ Branch 0 taken 3983250 times.
✗ Branch 1 not taken.
|
3983515 | Rdb_transaction *const tx = get_or_create_tx(thd); |
| 11690 |
1/2✓ Branch 0 taken 3983495 times.
✗ Branch 1 not taken.
|
3983250 | read_thd_vars(thd); |
| 11691 | |||
| 11692 |
3/4✓ Branch 0 taken 3983547 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 414242 times.
✓ Branch 3 taken 3569305 times.
|
3983495 | if (skip_unique_check()) { |
| 11693 |
2/2✓ Branch 0 taken 359 times.
✓ Branch 1 taken 413883 times.
|
414242 | if ((thd->lex->sql_command == SQLCOM_INSERT || |
| 11694 |
2/2✓ Branch 0 taken 223 times.
✓ Branch 1 taken 136 times.
|
359 | thd->lex->sql_command == SQLCOM_LOAD || |
| 11695 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 222 times.
|
223 | thd->lex->sql_command == SQLCOM_REPLACE) && |
| 11696 |
2/2✓ Branch 0 taken 414016 times.
✓ Branch 1 taken 4 times.
|
414020 | (thd->lex->duplicates == DUP_REPLACE || |
| 11697 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 414015 times.
|
414016 | thd->lex->duplicates == DUP_UPDATE)) { |
| 11698 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | my_error(ER_ON_DUPLICATE_DISABLED, MYF(0), thd->query().str); |
| 11699 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | DBUG_RETURN(HA_ERR_UNSUPPORTED); |
| 11700 | } | ||
| 11701 | } | ||
| 11702 | |||
| 11703 |
2/2✓ Branch 0 taken 3832978 times.
✓ Branch 1 taken 150564 times.
|
3983542 | if (lock_type == F_WRLCK) { |
| 11704 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3832901 times.
|
3832978 | if (tx->is_tx_read_only()) { |
| 11705 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_UPDATES_WITH_CONSISTENT_SNAPSHOT, MYF(0)); |
| 11706 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_ERR_UNSUPPORTED); |
| 11707 | } | ||
| 11708 | |||
| 11709 | /* | ||
| 11710 | SQL layer signals us to take a write lock. It does so when starting DML | ||
| 11711 | statement. We should put locks on the rows we're reading. | ||
| 11712 | |||
| 11713 | Note: sometimes, external_lock() can be called without a prior | ||
| 11714 | ::store_lock call. That's why we need to set lock_* members here, too. | ||
| 11715 | */ | ||
| 11716 | 3832901 | m_lock_rows = RDB_LOCK_WRITE; | |
| 11717 | |||
| 11718 |
1/2✓ Branch 0 taken 3833035 times.
✗ Branch 1 not taken.
|
3832901 | if (thd->lex->sql_command == SQLCOM_CREATE_INDEX || |
| 11719 |
1/2✓ Branch 0 taken 3833074 times.
✗ Branch 1 not taken.
|
3833035 | thd->lex->sql_command == SQLCOM_DROP_INDEX || |
| 11720 |
2/2✓ Branch 0 taken 1866 times.
✓ Branch 1 taken 3831208 times.
|
3833074 | thd->lex->sql_command == SQLCOM_ALTER_TABLE) { |
| 11721 | 1693 | tx->m_ddl_transaction = true; | |
| 11722 | } | ||
| 11723 | } | ||
| 11724 | 3983465 | tx->m_n_mysql_tables_in_use++; | |
| 11725 |
1/2✓ Branch 0 taken 3983706 times.
✗ Branch 1 not taken.
|
3983465 | rocksdb_register_tx(rocksdb_hton, thd, tx); |
| 11726 |
1/2✓ Branch 0 taken 3983838 times.
✗ Branch 1 not taken.
|
3983706 | tx->io_perf_start(&m_io_perf); |
| 11727 | } | ||
| 11728 | |||
| 11729 |
1/2✓ Branch 0 taken 7967523 times.
✗ Branch 1 not taken.
|
7967472 | DBUG_RETURN(res); |
| 11730 | } | ||
| 11731 | |||
| 11732 | /** | ||
| 11733 | @note | ||
| 11734 | A quote from ha_innobase::start_stmt(): | ||
| 11735 | <quote> | ||
| 11736 | MySQL calls this function at the start of each SQL statement inside LOCK | ||
| 11737 | TABLES. Inside LOCK TABLES the ::external_lock method does not work to | ||
| 11738 | mark SQL statement borders. | ||
| 11739 | </quote> | ||
| 11740 | |||
| 11741 | @return | ||
| 11742 | HA_EXIT_SUCCESS OK | ||
| 11743 | */ | ||
| 11744 | |||
| 11745 | 358 | int ha_rocksdb::start_stmt(THD *const thd, thr_lock_type lock_type) { | |
| 11746 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | DBUG_ENTER_FUNC(); |
| 11747 | |||
| 11748 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 358 times.
|
358 | assert(thd != nullptr); |
| 11749 | |||
| 11750 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | Rdb_transaction *const tx = get_or_create_tx(thd); |
| 11751 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | read_thd_vars(thd); |
| 11752 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | rocksdb_register_tx(ht, thd, tx); |
| 11753 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | tx->io_perf_start(&m_io_perf); |
| 11754 | |||
| 11755 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 11756 | } | ||
| 11757 | |||
| 11758 | 475697 | rocksdb::Range get_range(uint32_t i, | |
| 11759 | uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2], | ||
| 11760 | int offset1, int offset2) { | ||
| 11761 | 475697 | uchar *buf_begin = buf; | |
| 11762 | 475697 | uchar *buf_end = buf + Rdb_key_def::INDEX_NUMBER_SIZE; | |
| 11763 | 475697 | rdb_netbuf_store_index(buf_begin, i + offset1); | |
| 11764 | 475698 | rdb_netbuf_store_index(buf_end, i + offset2); | |
| 11765 | |||
| 11766 | return rocksdb::Range( | ||
| 11767 | 475697 | rocksdb::Slice((const char *)buf_begin, Rdb_key_def::INDEX_NUMBER_SIZE), | |
| 11768 | 951396 | rocksdb::Slice((const char *)buf_end, Rdb_key_def::INDEX_NUMBER_SIZE)); | |
| 11769 | } | ||
| 11770 | |||
| 11771 | 449296 | static rocksdb::Range get_range(const Rdb_key_def &kd, | |
| 11772 | uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2], | ||
| 11773 | int offset1, int offset2) { | ||
| 11774 | 449296 | return get_range(kd.get_index_number(), buf, offset1, offset2); | |
| 11775 | } | ||
| 11776 | |||
| 11777 | 449296 | rocksdb::Range ha_rocksdb::get_range( | |
| 11778 | const Rdb_key_def &kd, uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]) { | ||
| 11779 |
2/2✓ Branch 0 taken 121777 times.
✓ Branch 1 taken 327519 times.
|
449296 | if (kd.m_is_reverse_cf) { |
| 11780 | 121777 | return myrocks::get_range(kd, buf, 1, 0); | |
| 11781 | } else { | ||
| 11782 | 327519 | return myrocks::get_range(kd, buf, 0, 1); | |
| 11783 | } | ||
| 11784 | } | ||
| 11785 | |||
| 11786 | 231 | rocksdb::Range ha_rocksdb::get_range( | |
| 11787 | const int i, uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]) const { | ||
| 11788 | 231 | return get_range(*m_key_descr_arr[i], buf); | |
| 11789 | } | ||
| 11790 | |||
| 11791 | /* | ||
| 11792 | This function is called with total_order_seek=true, but | ||
| 11793 | upper/lower bound setting is not necessary. | ||
| 11794 | Boundary set is useful when there is no matching key, | ||
| 11795 | but in drop_index_thread's case, it means index is marked as removed, | ||
| 11796 | so no further seek will happen for the index id. | ||
| 11797 | */ | ||
| 11798 | 26397 | static bool is_myrocks_index_empty(rocksdb::ColumnFamilyHandle *cfh, | |
| 11799 | const bool is_reverse_cf, | ||
| 11800 | const rocksdb::ReadOptions &read_opts, | ||
| 11801 | const uint index_id) { | ||
| 11802 | 26397 | bool index_removed = false; | |
| 11803 | 26397 | uchar key_buf[Rdb_key_def::INDEX_NUMBER_SIZE] = {0}; | |
| 11804 | 26397 | rdb_netbuf_store_uint32(key_buf, index_id); | |
| 11805 | const rocksdb::Slice key = | ||
| 11806 | 26397 | rocksdb::Slice(reinterpret_cast<char *>(key_buf), sizeof(key_buf)); | |
| 11807 |
1/2✓ Branch 0 taken 26397 times.
✗ Branch 1 not taken.
|
26397 | std::unique_ptr<rocksdb::Iterator> it(rdb->NewIterator(read_opts, cfh)); |
| 11808 |
1/2✓ Branch 0 taken 26397 times.
✗ Branch 1 not taken.
|
26397 | rocksdb_smart_seek(is_reverse_cf, it.get(), key); |
| 11809 |
3/4✓ Branch 0 taken 26397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16821 times.
✓ Branch 3 taken 9576 times.
|
26397 | if (!it->Valid()) { |
| 11810 | 16821 | index_removed = true; | |
| 11811 | } else { | ||
| 11812 |
3/4✓ Branch 0 taken 9576 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9541 times.
✓ Branch 3 taken 35 times.
|
9576 | if (memcmp(it->key().data(), key_buf, Rdb_key_def::INDEX_NUMBER_SIZE)) { |
| 11813 | // Key does not have same prefix | ||
| 11814 | 9541 | index_removed = true; | |
| 11815 | } | ||
| 11816 | } | ||
| 11817 | 26397 | return index_removed; | |
| 11818 | 26397 | } | |
| 11819 | |||
| 11820 | /* | ||
| 11821 | Drop index thread's main logic | ||
| 11822 | */ | ||
| 11823 | |||
| 11824 | 902 | void Rdb_drop_index_thread::run() { | |
| 11825 |
2/4✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
✗ Branch 3 not taken.
|
902 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 11826 |
1/2✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
|
902 | auto dict_manager_list = dict_manager.get_all_dict_manager_selector(); |
| 11827 | for (;;) { | ||
| 11828 | // The stop flag might be set by shutdown command | ||
| 11829 | // after drop_index_thread releases signal_mutex | ||
| 11830 | // (i.e. while executing expensive Seek()). To prevent drop_index_thread | ||
| 11831 | // from entering long cond_timedwait, checking if stop flag | ||
| 11832 | // is true or not is needed, with drop_index_interrupt_mutex held. | ||
| 11833 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12836 times.
|
12840 | if (m_killed) { |
| 11834 | 4 | break; | |
| 11835 | } | ||
| 11836 | timespec ts; | ||
| 11837 | 12836 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 11838 | 12836 | bool is_drop_index_empty = true; | |
| 11839 |
2/2✓ Branch 0 taken 12944 times.
✓ Branch 1 taken 11217 times.
|
24161 | for (Rdb_dict_manager *local_dict_manager : dict_manager_list) { |
| 11840 |
3/4✓ Branch 0 taken 12944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1619 times.
✓ Branch 3 taken 11325 times.
|
12944 | if (!local_dict_manager->is_drop_index_empty()) { |
| 11841 | 1619 | is_drop_index_empty = false; | |
| 11842 | 1619 | break; | |
| 11843 | } | ||
| 11844 | } | ||
| 11845 |
2/2✓ Branch 0 taken 11217 times.
✓ Branch 1 taken 1619 times.
|
12836 | ts.tv_sec += is_drop_index_empty ? 24 * 60 * 60 // no filtering |
| 11846 | : 60; // filtering | ||
| 11847 | |||
| 11848 | const auto ret MY_ATTRIBUTE((__unused__)) = | ||
| 11849 |
1/2✓ Branch 0 taken 12800 times.
✗ Branch 1 not taken.
|
12836 | mysql_cond_timedwait(&m_signal_cond, &m_signal_mutex, &ts); |
| 11850 |
2/2✓ Branch 0 taken 862 times.
✓ Branch 1 taken 11938 times.
|
12800 | if (m_killed) { |
| 11851 | 862 | break; | |
| 11852 | } | ||
| 11853 | // make sure, no program error is returned | ||
| 11854 |
3/4✓ Branch 0 taken 49 times.
✓ Branch 1 taken 11889 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
|
11938 | assert(ret == 0 || ret == ETIMEDOUT); |
| 11855 |
2/4✓ Branch 0 taken 11938 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11938 times.
✗ Branch 3 not taken.
|
11938 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 11856 |
2/2✓ Branch 0 taken 12049 times.
✓ Branch 1 taken 11938 times.
|
23987 | for (Rdb_dict_manager *local_dict_manager : dict_manager_list) { |
| 11857 | 12049 | std::unordered_set<GL_INDEX_ID> indices; | |
| 11858 |
1/2✓ Branch 0 taken 12049 times.
✗ Branch 1 not taken.
|
12049 | local_dict_manager->get_ongoing_drop_indexes(&indices); |
| 11859 |
2/2✓ Branch 0 taken 11648 times.
✓ Branch 1 taken 401 times.
|
12049 | if (!indices.empty()) { |
| 11860 | 11648 | std::unordered_set<GL_INDEX_ID> finished; | |
| 11861 |
1/2✓ Branch 0 taken 11648 times.
✗ Branch 1 not taken.
|
11648 | rocksdb::ReadOptions read_opts; |
| 11862 | 11648 | read_opts.total_order_seek = true; // disable bloom filter | |
| 11863 | |||
| 11864 |
2/2✓ Branch 0 taken 26407 times.
✓ Branch 1 taken 11644 times.
|
38051 | for (const auto d : indices) { |
| 11865 | 26407 | uint32 cf_flags = 0; | |
| 11866 |
2/4✓ Branch 0 taken 26407 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26407 times.
|
26407 | if (!local_dict_manager->get_cf_flags(d.cf_id, &cf_flags)) { |
| 11867 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 11868 | "Failed to get column family flags " | ||
| 11869 | "from cf id %u. MyRocks data dictionary may " | ||
| 11870 | "get corrupted.", | ||
| 11871 | d.cf_id); | ||
| 11872 | ✗ | abort(); | |
| 11873 | } | ||
| 11874 | |||
| 11875 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 11876 |
1/2✓ Branch 0 taken 26407 times.
✗ Branch 1 not taken.
|
26407 | cf_manager.get_cf(d.cf_id); |
| 11877 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26407 times.
|
26407 | assert(cfh); |
| 11878 | |||
| 11879 |
3/4✓ Branch 0 taken 26407 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 26401 times.
|
26407 | if (local_dict_manager->get_dropped_cf(d.cf_id)) { |
| 11880 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | finished.insert(d); |
| 11881 | 6 | continue; | |
| 11882 | } | ||
| 11883 | |||
| 11884 | 26401 | const bool is_reverse_cf = cf_flags & Rdb_key_def::REVERSE_CF_FLAG; | |
| 11885 | |||
| 11886 | uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]; | ||
| 11887 |
4/4✓ Branch 0 taken 467 times.
✓ Branch 1 taken 25934 times.
✓ Branch 2 taken 467 times.
✓ Branch 3 taken 25934 times.
|
26401 | rocksdb::Range range = get_range( |
| 11888 |
1/2✓ Branch 0 taken 26401 times.
✗ Branch 1 not taken.
|
26401 | d.index_id, buf, is_reverse_cf ? 1 : 0, is_reverse_cf ? 0 : 1); |
| 11889 | |||
| 11890 | rocksdb::Status status = DeleteFilesInRange( | ||
| 11891 |
2/4✓ Branch 0 taken 26401 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26401 times.
✗ Branch 3 not taken.
|
26401 | rdb->GetBaseDB(), cfh.get(), &range.start, &range.limit); |
| 11892 |
2/4✓ Branch 0 taken 26401 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26401 times.
|
26401 | if (!status.ok()) { |
| 11893 | ✗ | if (status.IsIncomplete()) { | |
| 11894 | ✗ | continue; | |
| 11895 | ✗ | } else if (status.IsShutdownInProgress()) { | |
| 11896 | ✗ | break; | |
| 11897 | } | ||
| 11898 | ✗ | rdb_handle_io_error(status, RDB_IO_ERROR_BG_THREAD); | |
| 11899 | } | ||
| 11900 | |||
| 11901 |
1/2✓ Branch 0 taken 26401 times.
✗ Branch 1 not taken.
|
52802 | status = rdb->CompactRange(getCompactRangeOptions(), cfh.get(), |
| 11902 | 26401 | &range.start, &range.limit); | |
| 11903 |
3/4✓ Branch 0 taken 26401 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 26397 times.
|
26401 | if (!status.ok()) { |
| 11904 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (status.IsIncomplete()) { |
| 11905 | ✗ | continue; | |
| 11906 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | } else if (status.IsShutdownInProgress()) { |
| 11907 | 4 | break; | |
| 11908 | } | ||
| 11909 | ✗ | rdb_handle_io_error(status, RDB_IO_ERROR_BG_THREAD); | |
| 11910 | } | ||
| 11911 |
3/4✓ Branch 0 taken 26397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26362 times.
✓ Branch 3 taken 35 times.
|
26397 | if (is_myrocks_index_empty(cfh.get(), is_reverse_cf, read_opts, |
| 11912 | 26397 | d.index_id)) { | |
| 11913 |
1/2✓ Branch 0 taken 26362 times.
✗ Branch 1 not taken.
|
26362 | finished.insert(d); |
| 11914 | } | ||
| 11915 |
5/6✓ Branch 0 taken 26397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 26397 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 4 times.
|
26411 | } |
| 11916 | |||
| 11917 |
2/2✓ Branch 0 taken 11630 times.
✓ Branch 1 taken 18 times.
|
11648 | if (!finished.empty()) { |
| 11918 |
1/2✓ Branch 0 taken 11630 times.
✗ Branch 1 not taken.
|
11630 | local_dict_manager->finish_drop_indexes(finished); |
| 11919 | } | ||
| 11920 | 11648 | } | |
| 11921 | |||
| 11922 |
10/18✓ Branch 0 taken 12049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 12005 times.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 44 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 44 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 44 times.
✓ Branch 14 taken 44 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 44 times.
✗ Branch 17 not taken.
|
12049 | DBUG_EXECUTE_IF("rocksdb_drop_cf", { |
| 11923 | THD *thd = new THD(); | ||
| 11924 | thd->thread_stack = reinterpret_cast<char *>(&(thd)); | ||
| 11925 | thd->store_globals(); | ||
| 11926 | |||
| 11927 | static const char act[] = "now wait_for ready_to_drop_cf"; | ||
| 11928 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 11929 | |||
| 11930 | thd->restore_globals(); | ||
| 11931 | delete thd; | ||
| 11932 | }); | ||
| 11933 | |||
| 11934 | // Remove dropped column family | ||
| 11935 | // 1. Get all cf ids from ongoing_index_drop. | ||
| 11936 | // 2. Get all cf ids for cfs marked as dropped. | ||
| 11937 | // 3. If a cf id is in the list of ongoing_index_drop | ||
| 11938 | // , skip removing this cf. It will be removed later. | ||
| 11939 | // 4. If it is not, proceed to remove the cf. | ||
| 11940 | // | ||
| 11941 | // This should be under dict_manager lock | ||
| 11942 | |||
| 11943 | { | ||
| 11944 |
1/2✓ Branch 0 taken 12049 times.
✗ Branch 1 not taken.
|
12049 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 11945 | 12049 | std::unordered_set<uint32> dropped_cf_ids; | |
| 11946 |
1/2✓ Branch 0 taken 12049 times.
✗ Branch 1 not taken.
|
12049 | local_dict_manager->get_all_dropped_cfs(&dropped_cf_ids); |
| 11947 | |||
| 11948 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 12011 times.
|
12049 | if (!dropped_cf_ids.empty()) { |
| 11949 | 38 | std::unordered_set<GL_INDEX_ID> ongoing_drop_indices; | |
| 11950 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | local_dict_manager->get_ongoing_drop_indexes(&ongoing_drop_indices); |
| 11951 | |||
| 11952 | 38 | std::unordered_set<uint32> ongoing_drop_cf_ids; | |
| 11953 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | for (const auto index : ongoing_drop_indices) { |
| 11954 | ✗ | ongoing_drop_cf_ids.insert(index.cf_id); | |
| 11955 | } | ||
| 11956 | |||
| 11957 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 38 times.
|
76 | for (const auto cf_id : dropped_cf_ids) { |
| 11958 |
2/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | if (ongoing_drop_cf_ids.find(cf_id) == ongoing_drop_cf_ids.end()) { |
| 11959 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | cf_manager.remove_dropped_cf(local_dict_manager, rdb, cf_id); |
| 11960 | } | ||
| 11961 | } | ||
| 11962 | 38 | } | |
| 11963 | 12049 | } | |
| 11964 | |||
| 11965 |
13/24✓ Branch 0 taken 12049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 12007 times.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 42 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 42 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 42 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 42 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 42 times.
✓ Branch 20 taken 42 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 42 times.
✗ Branch 23 not taken.
|
12091 | DBUG_EXECUTE_IF("rocksdb_drop_cf", { |
| 11966 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); | ||
| 11967 | std::unordered_set<uint32> dropped_cf_ids; | ||
| 11968 | local_dict_manager->get_all_dropped_cfs(&dropped_cf_ids); | ||
| 11969 | if (dropped_cf_ids.empty()) { | ||
| 11970 | THD *thd = new THD(); | ||
| 11971 | thd->thread_stack = reinterpret_cast<char *>(&(thd)); | ||
| 11972 | thd->store_globals(); | ||
| 11973 | |||
| 11974 | static const char act[] = "now signal drop_cf_done"; | ||
| 11975 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 11976 | |||
| 11977 | thd->restore_globals(); | ||
| 11978 | delete thd; | ||
| 11979 | } | ||
| 11980 | }); | ||
| 11981 | 12049 | } | |
| 11982 |
2/4✓ Branch 0 taken 11938 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11938 times.
✗ Branch 3 not taken.
|
11938 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 11983 | 11938 | } | |
| 11984 | |||
| 11985 |
2/4✓ Branch 0 taken 866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 866 times.
✗ Branch 3 not taken.
|
866 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 11986 | 866 | } | |
| 11987 | |||
| 11988 | 11983 | Rdb_tbl_def *ha_rocksdb::get_table_if_exists(const char *const tablename) { | |
| 11989 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11983 times.
|
11983 | assert(tablename != nullptr); |
| 11990 | |||
| 11991 | 11983 | std::string str; | |
| 11992 |
3/6✓ Branch 0 taken 11983 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11984 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11984 times.
|
11983 | if (rdb_normalize_tablename(tablename, &str) != HA_EXIT_SUCCESS) { |
| 11993 | // We were not passed table name? | ||
| 11994 | ✗ | assert(0); | |
| 11995 | return nullptr; | ||
| 11996 | } | ||
| 11997 | |||
| 11998 |
1/2✓ Branch 0 taken 11983 times.
✗ Branch 1 not taken.
|
11984 | return ddl_manager.find(str); |
| 11999 | 11983 | } | |
| 12000 | |||
| 12001 | /* | ||
| 12002 | Overload func for delete table ---it deletes table meta data in data | ||
| 12003 | dictionary immediately and delete real data in background thread(async) | ||
| 12004 | |||
| 12005 | @param tbl IN MyRocks table definition | ||
| 12006 | |||
| 12007 | @return | ||
| 12008 | HA_EXIT_SUCCESS OK | ||
| 12009 | other HA_ERR error code (can be SE-specific) | ||
| 12010 | */ | ||
| 12011 | 14461 | int ha_rocksdb::delete_table(Rdb_tbl_def *const tbl) { | |
| 12012 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14461 | DBUG_ENTER_FUNC(); |
| 12013 | |||
| 12014 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14463 times.
|
14463 | assert(tbl != nullptr); |
| 12015 |
3/4✓ Branch 0 taken 2599 times.
✓ Branch 1 taken 11864 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2599 times.
|
14463 | assert(m_tbl_def == nullptr || m_tbl_def == tbl); |
| 12016 |
1/2✓ Branch 0 taken 14461 times.
✗ Branch 1 not taken.
|
14463 | uint table_default_cf_id = tbl->m_key_descr_arr[0]->get_gl_index_id().cf_id; |
| 12017 | auto local_dict_manager = | ||
| 12018 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14461 | dict_manager.get_dict_manager_selector_non_const(table_default_cf_id); |
| 12019 |
1/2✓ Branch 0 taken 14462 times.
✗ Branch 1 not taken.
|
14463 | const std::unique_ptr<rocksdb::WriteBatch> wb = local_dict_manager->begin(); |
| 12020 | 14462 | rocksdb::WriteBatch *const batch = wb.get(); | |
| 12021 | |||
| 12022 |
6/10✓ Branch 0 taken 14462 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 14456 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
|
14462 | DBUG_EXECUTE_IF("rocksdb_before_delete_table", { |
| 12023 | static constexpr char act[] = | ||
| 12024 | "now signal ready_to_mark_cf_dropped_before_delete_table wait_for " | ||
| 12025 | "mark_cf_dropped_done_before_delete_table"; | ||
| 12026 | assert(!debug_sync_set_action(ha_thd(), STRING_WITH_LEN(act))); | ||
| 12027 | }); | ||
| 12028 | |||
| 12029 | { | ||
| 12030 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14462 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 12031 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14463 | local_dict_manager->add_drop_table(tbl->m_key_descr_arr, tbl->m_key_count, |
| 12032 | batch); | ||
| 12033 | |||
| 12034 | /* | ||
| 12035 | Remove the table entry in data dictionary (this will also remove it from | ||
| 12036 | the persistent data dictionary). | ||
| 12037 | */ | ||
| 12038 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14463 | ddl_manager.remove(tbl, batch, table_default_cf_id, true); |
| 12039 | |||
| 12040 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14463 | int err = local_dict_manager->commit(batch); |
| 12041 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14463 times.
|
14463 | if (err) { |
| 12042 | ✗ | DBUG_RETURN(err); | |
| 12043 | } | ||
| 12044 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14463 | } |
| 12045 | |||
| 12046 |
6/10✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 14457 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
|
14463 | DBUG_EXECUTE_IF("rocksdb_after_delete_table", { |
| 12047 | static constexpr char act[] = | ||
| 12048 | "now signal ready_to_mark_cf_dropped_after_delete_table " | ||
| 12049 | "wait_for mark_cf_dropped_done_after_delete_table"; | ||
| 12050 | assert(!debug_sync_set_action(ha_thd(), STRING_WITH_LEN(act))); | ||
| 12051 | }); | ||
| 12052 | |||
| 12053 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14463 | rdb_drop_idx_thread.signal(); |
| 12054 | // avoid dangling pointer | ||
| 12055 | 14463 | m_tbl_def = nullptr; | |
| 12056 |
1/2✓ Branch 0 taken 14463 times.
✗ Branch 1 not taken.
|
14463 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12057 | 14463 | } | |
| 12058 | |||
| 12059 | /* | ||
| 12060 | Note: the following function is called when the table is not open. That is, | ||
| 12061 | this->table==nullptr, pk_key_descr==nullptr, etc. | ||
| 12062 | |||
| 12063 | tablename points to line in form "./dbname/tablename". | ||
| 12064 | |||
| 12065 | @return | ||
| 12066 | HA_EXIT_SUCCESS OK | ||
| 12067 | other HA_ERR error code (can be SE-specific) | ||
| 12068 | */ | ||
| 12069 | |||
| 12070 | 11983 | int ha_rocksdb::delete_table(const char *const tablename, | |
| 12071 | const dd::Table *table_def | ||
| 12072 | MY_ATTRIBUTE((__unused__))) { | ||
| 12073 |
1/2✓ Branch 0 taken 11984 times.
✗ Branch 1 not taken.
|
11983 | DBUG_ENTER_FUNC(); |
| 12074 | |||
| 12075 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11984 times.
|
11984 | assert(tablename != nullptr); |
| 12076 | |||
| 12077 | /* Find the table in the hash */ | ||
| 12078 |
1/2✓ Branch 0 taken 11983 times.
✗ Branch 1 not taken.
|
11984 | Rdb_tbl_def *const tbl = get_table_if_exists(tablename); |
| 12079 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11971 times.
|
11983 | if (!tbl) { |
| 12080 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); |
| 12081 | } | ||
| 12082 | |||
| 12083 |
2/4✓ Branch 0 taken 11972 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11972 times.
✗ Branch 3 not taken.
|
11971 | DBUG_RETURN(delete_table(tbl)); |
| 12084 | } | ||
| 12085 | |||
| 12086 | /** | ||
| 12087 | @return | ||
| 12088 | HA_EXIT_SUCCESS OK | ||
| 12089 | other HA_ERR error code (cannot be SE-specific) | ||
| 12090 | */ | ||
| 12091 | 5128 | int ha_rocksdb::rename_table( | |
| 12092 | const char *const from, const char *const to, | ||
| 12093 | const dd::Table *from_table_def MY_ATTRIBUTE((__unused__)), | ||
| 12094 | dd::Table *to_table_def MY_ATTRIBUTE((__unused__))) { | ||
| 12095 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | DBUG_ENTER_FUNC(); |
| 12096 | |||
| 12097 | 5128 | std::string from_str; | |
| 12098 | 5128 | std::string to_str; | |
| 12099 | 5128 | std::string from_db; | |
| 12100 | 5128 | std::string to_db; | |
| 12101 | int rc; | ||
| 12102 | |||
| 12103 |
4/6✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5128 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2509 times.
✓ Branch 5 taken 2619 times.
|
5128 | if (rdb_is_tablename_normalized(from)) { |
| 12104 |
1/2✓ Branch 0 taken 2509 times.
✗ Branch 1 not taken.
|
2509 | from_str = from; |
| 12105 | } else { | ||
| 12106 |
2/4✓ Branch 0 taken 2619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2619 times.
✗ Branch 3 not taken.
|
2619 | rc = rdb_normalize_tablename(from, &from_str); |
| 12107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2619 times.
|
2619 | if (rc != HA_EXIT_SUCCESS) { |
| 12108 | ✗ | DBUG_RETURN(rc); | |
| 12109 | } | ||
| 12110 | } | ||
| 12111 | |||
| 12112 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | rc = rdb_split_normalized_tablename(from_str, &from_db); |
| 12113 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5128 times.
|
5128 | if (rc != HA_EXIT_SUCCESS) { |
| 12114 | ✗ | DBUG_RETURN(rc); | |
| 12115 | } | ||
| 12116 | |||
| 12117 |
4/6✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5128 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2509 times.
✓ Branch 5 taken 2619 times.
|
5128 | if (rdb_is_tablename_normalized(to)) { |
| 12118 |
1/2✓ Branch 0 taken 2509 times.
✗ Branch 1 not taken.
|
2509 | to_str = to; |
| 12119 | } else { | ||
| 12120 |
2/4✓ Branch 0 taken 2619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2619 times.
✗ Branch 3 not taken.
|
2619 | rc = rdb_normalize_tablename(to, &to_str); |
| 12121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2619 times.
|
2619 | if (rc != HA_EXIT_SUCCESS) { |
| 12122 | ✗ | DBUG_RETURN(rc); | |
| 12123 | } | ||
| 12124 | } | ||
| 12125 | |||
| 12126 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | rc = rdb_split_normalized_tablename(to_str, &to_db); |
| 12127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5128 times.
|
5128 | if (rc != HA_EXIT_SUCCESS) { |
| 12128 | ✗ | DBUG_RETURN(rc); | |
| 12129 | } | ||
| 12130 | |||
| 12131 | // If the user changed the database part of the name then validate that the | ||
| 12132 | // 'to' database exists. | ||
| 12133 |
5/8✓ Branch 0 taken 86 times.
✓ Branch 1 taken 5042 times.
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5128 times.
|
5128 | if (from_db != to_db && !rdb_database_exists(to_db)) { |
| 12134 | // If we return a RocksDB specific error code here we get | ||
| 12135 | // "error: 206 - Unknown error 206". InnoDB gets | ||
| 12136 | // "error -1 - Unknown error -1" so let's match them. | ||
| 12137 | ✗ | DBUG_RETURN(-1); | |
| 12138 | } | ||
| 12139 | |||
| 12140 |
4/6✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5125 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
5128 | DBUG_EXECUTE_IF("gen_sql_table_name", to_str = to_str + "_rdb_only";); |
| 12141 | |||
| 12142 | auto local_dict_manager = | ||
| 12143 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | dict_manager.get_dict_manager_selector_non_const(is_tmp_table(from_str)); |
| 12144 | |||
| 12145 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | const std::unique_ptr<rocksdb::WriteBatch> wb = local_dict_manager->begin(); |
| 12146 | 5128 | rocksdb::WriteBatch *const batch = wb.get(); | |
| 12147 | |||
| 12148 | // rename table is under dict_manager lock, and the cfs used | ||
| 12149 | // by indices of this table cannot be dropped during the process. | ||
| 12150 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 12151 |
2/4✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5128 times.
|
5128 | if (ddl_manager.rename(from_str, to_str, batch)) { |
| 12152 | ✗ | rc = HA_ERR_ROCKSDB_INVALID_TABLE; | |
| 12153 | } else { | ||
| 12154 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | rc = local_dict_manager->commit(batch); |
| 12155 | } | ||
| 12156 |
1/2✓ Branch 0 taken 5128 times.
✗ Branch 1 not taken.
|
5128 | DBUG_RETURN(rc); |
| 12157 | 5128 | } | |
| 12158 | |||
| 12159 | /** | ||
| 12160 | check_if_incompatible_data() called if ALTER TABLE can't detect otherwise | ||
| 12161 | if new and old definition are compatible | ||
| 12162 | |||
| 12163 | @details If there are no other explicit signs like changed number of | ||
| 12164 | fields this function will be called by compare_tables() | ||
| 12165 | (sql/sql_tables.cc) to decide should we rewrite whole table or only .frm | ||
| 12166 | file. | ||
| 12167 | |||
| 12168 | */ | ||
| 12169 | |||
| 12170 | ✗ | bool ha_rocksdb::check_if_incompatible_data(HA_CREATE_INFO *const info, | |
| 12171 | uint table_changes) { | ||
| 12172 | ✗ | DBUG_ENTER_FUNC(); | |
| 12173 | |||
| 12174 | ✗ | assert(info != nullptr); | |
| 12175 | |||
| 12176 | // this function is needed only for online alter-table | ||
| 12177 | ✗ | DBUG_RETURN(COMPATIBLE_DATA_NO); | |
| 12178 | } | ||
| 12179 | |||
| 12180 | /** | ||
| 12181 | @return | ||
| 12182 | HA_EXIT_SUCCESS OK | ||
| 12183 | */ | ||
| 12184 | 32156675 | int ha_rocksdb::extra(enum ha_extra_function operation) { | |
| 12185 |
1/2✓ Branch 0 taken 32157674 times.
✗ Branch 1 not taken.
|
32156675 | DBUG_ENTER_FUNC(); |
| 12186 | |||
| 12187 |
5/6✓ Branch 0 taken 128323 times.
✓ Branch 1 taken 128287 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 237 times.
✓ Branch 4 taken 4080790 times.
✓ Branch 5 taken 27820037 times.
|
32157674 | switch (operation) { |
| 12188 | 128323 | case HA_EXTRA_KEYREAD: | |
| 12189 | 128323 | m_keyread_only = true; | |
| 12190 | 128323 | break; | |
| 12191 | 128287 | case HA_EXTRA_NO_KEYREAD: | |
| 12192 | 128287 | m_keyread_only = false; | |
| 12193 | 128287 | break; | |
| 12194 | ✗ | case HA_EXTRA_FLUSH: | |
| 12195 | /* | ||
| 12196 | If the table has blobs, then they are part of m_retrieved_record. | ||
| 12197 | This call invalidates them. | ||
| 12198 | */ | ||
| 12199 | ✗ | m_retrieved_record.Reset(); | |
| 12200 | ✗ | m_dup_key_retrieved_record.Reset(); | |
| 12201 | ✗ | break; | |
| 12202 | 237 | case HA_EXTRA_INSERT_WITH_UPDATE: | |
| 12203 | // INSERT ON DUPLICATE KEY UPDATE | ||
| 12204 |
2/2✓ Branch 0 taken 210 times.
✓ Branch 1 taken 27 times.
|
237 | if (rocksdb_enable_insert_with_update_caching) { |
| 12205 | 210 | m_insert_with_update = true; | |
| 12206 | } | ||
| 12207 | 237 | break; | |
| 12208 | 4080790 | case HA_EXTRA_NO_IGNORE_DUP_KEY: | |
| 12209 | // PAIRED with HA_EXTRA_INSERT_WITH_UPDATE or HA_EXTRA_WRITE_CAN_REPLACE | ||
| 12210 | // that indicates the end of REPLACE / INSERT ON DUPLICATE KEY | ||
| 12211 | 4080790 | m_insert_with_update = false; | |
| 12212 | 4080790 | break; | |
| 12213 | |||
| 12214 | 27820037 | default: | |
| 12215 | 27820037 | break; | |
| 12216 | } | ||
| 12217 | |||
| 12218 |
1/2✓ Branch 0 taken 32157745 times.
✗ Branch 1 not taken.
|
32157674 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12219 | } | ||
| 12220 | |||
| 12221 | /* | ||
| 12222 | Given a starting key and an ending key, estimate the number of rows that | ||
| 12223 | will exist between the two keys. | ||
| 12224 | */ | ||
| 12225 | 227285 | ha_rows ha_rocksdb::records_in_range(uint inx, key_range *const min_key, | |
| 12226 | key_range *const max_key) { | ||
| 12227 |
1/2✓ Branch 0 taken 227285 times.
✗ Branch 1 not taken.
|
227285 | DBUG_ENTER_FUNC(); |
| 12228 | |||
| 12229 |
2/4✓ Branch 0 taken 227285 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 227285 times.
✗ Branch 3 not taken.
|
227285 | ha_rows ret = THDVAR(ha_thd(), records_in_range); |
| 12230 |
2/2✓ Branch 0 taken 28898 times.
✓ Branch 1 taken 198387 times.
|
227285 | if (ret) { |
| 12231 |
1/2✓ Branch 0 taken 28898 times.
✗ Branch 1 not taken.
|
28898 | DBUG_RETURN(ret); |
| 12232 | } | ||
| 12233 |
2/2✓ Branch 0 taken 122666 times.
✓ Branch 1 taken 75721 times.
|
198387 | if (table->force_index) { |
| 12234 |
2/4✓ Branch 0 taken 122666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 122666 times.
✗ Branch 3 not taken.
|
122666 | const ha_rows force_rows = THDVAR(ha_thd(), force_index_records_in_range); |
| 12235 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 122663 times.
|
122666 | if (force_rows) { |
| 12236 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(force_rows); |
| 12237 | } | ||
| 12238 | } | ||
| 12239 | |||
| 12240 | 198384 | const Rdb_key_def &kd = *m_key_descr_arr[inx]; | |
| 12241 | |||
| 12242 | 198384 | auto disk_size = kd.m_stats.m_actual_disk_size; | |
| 12243 |
2/2✓ Branch 0 taken 8707 times.
✓ Branch 1 taken 189677 times.
|
198384 | if (disk_size == 0) disk_size = kd.m_stats.m_data_size; |
| 12244 | 198384 | auto rows = kd.m_stats.m_rows; | |
| 12245 |
3/4✓ Branch 0 taken 189677 times.
✓ Branch 1 taken 8707 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 189677 times.
|
198384 | if (rows == 0 || disk_size == 0) { |
| 12246 | 8707 | rows = 1; | |
| 12247 | 8707 | disk_size = ROCKSDB_ASSUMED_KEY_VALUE_DISK_SIZE; | |
| 12248 | } | ||
| 12249 | 198384 | ulonglong total_size = 0; | |
| 12250 | 198384 | ulonglong total_row = 0; | |
| 12251 |
1/2✓ Branch 0 taken 198384 times.
✗ Branch 1 not taken.
|
198384 | records_in_range_internal(inx, min_key, max_key, disk_size, rows, &total_size, |
| 12252 | &total_row); | ||
| 12253 | 198384 | ret = total_row; | |
| 12254 | /* | ||
| 12255 | GetApproximateSizes() gives estimates so ret might exceed stats.records. | ||
| 12256 | MySQL then decides to use full index scan rather than range scan, which | ||
| 12257 | is not efficient for most cases. | ||
| 12258 | To prevent this, changing estimated records slightly smaller than | ||
| 12259 | stats.records. | ||
| 12260 | */ | ||
| 12261 |
2/2✓ Branch 0 taken 2446 times.
✓ Branch 1 taken 195938 times.
|
198384 | if (ret >= stats.records) { |
| 12262 | 2446 | ret = stats.records * 0.99; | |
| 12263 | } | ||
| 12264 | |||
| 12265 |
2/2✓ Branch 0 taken 3039 times.
✓ Branch 1 taken 195345 times.
|
198384 | if (rocksdb_debug_optimizer_n_rows > 0) { |
| 12266 | 3039 | ret = rocksdb_debug_optimizer_n_rows; | |
| 12267 |
2/2✓ Branch 0 taken 137322 times.
✓ Branch 1 taken 58023 times.
|
195345 | } else if (ret == 0) { |
| 12268 | 137322 | ret = 1; | |
| 12269 | } | ||
| 12270 | |||
| 12271 |
1/2✓ Branch 0 taken 198384 times.
✗ Branch 1 not taken.
|
198384 | DBUG_RETURN(ret); |
| 12272 | } | ||
| 12273 | |||
| 12274 | 198384 | void ha_rocksdb::records_in_range_internal(uint inx, key_range *const min_key, | |
| 12275 | key_range *const max_key, | ||
| 12276 | int64 disk_size, int64 rows, | ||
| 12277 | ulonglong *total_size, | ||
| 12278 | ulonglong *row_count) { | ||
| 12279 |
1/2✓ Branch 0 taken 198384 times.
✗ Branch 1 not taken.
|
198384 | DBUG_ENTER_FUNC(); |
| 12280 | |||
| 12281 | 198384 | const Rdb_key_def &kd = *m_key_descr_arr[inx]; | |
| 12282 | |||
| 12283 | 198384 | uint size1 = 0; | |
| 12284 |
2/2✓ Branch 0 taken 197986 times.
✓ Branch 1 taken 398 times.
|
198384 | if (min_key) { |
| 12285 | 395972 | size1 = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple, | |
| 12286 |
1/2✓ Branch 0 taken 197986 times.
✗ Branch 1 not taken.
|
197986 | min_key->key, min_key->keypart_map); |
| 12287 |
1/2✓ Branch 0 taken 197986 times.
✗ Branch 1 not taken.
|
197986 | if (min_key->flag == HA_READ_PREFIX_LAST_OR_PREV || |
| 12288 |
1/2✓ Branch 0 taken 197986 times.
✗ Branch 1 not taken.
|
197986 | min_key->flag == HA_READ_PREFIX_LAST || |
| 12289 |
2/2✓ Branch 0 taken 778 times.
✓ Branch 1 taken 197208 times.
|
197986 | min_key->flag == HA_READ_AFTER_KEY) { |
| 12290 |
1/2✓ Branch 0 taken 778 times.
✗ Branch 1 not taken.
|
778 | kd.successor(m_sk_packed_tuple, size1); |
| 12291 | } | ||
| 12292 | } else { | ||
| 12293 | 398 | kd.get_infimum_key(m_sk_packed_tuple, &size1); | |
| 12294 | } | ||
| 12295 | |||
| 12296 | 198384 | uint size2 = 0; | |
| 12297 |
2/2✓ Branch 0 taken 196700 times.
✓ Branch 1 taken 1684 times.
|
198384 | if (max_key) { |
| 12298 | 393400 | size2 = kd.pack_index_tuple(table, m_pack_buffer, m_sk_packed_tuple_old, | |
| 12299 |
1/2✓ Branch 0 taken 196700 times.
✗ Branch 1 not taken.
|
196700 | max_key->key, max_key->keypart_map); |
| 12300 |
1/2✓ Branch 0 taken 196700 times.
✗ Branch 1 not taken.
|
196700 | if (max_key->flag == HA_READ_PREFIX_LAST_OR_PREV || |
| 12301 |
1/2✓ Branch 0 taken 196700 times.
✗ Branch 1 not taken.
|
196700 | max_key->flag == HA_READ_PREFIX_LAST || |
| 12302 |
2/2✓ Branch 0 taken 195965 times.
✓ Branch 1 taken 735 times.
|
196700 | max_key->flag == HA_READ_AFTER_KEY) { |
| 12303 |
1/2✓ Branch 0 taken 195965 times.
✗ Branch 1 not taken.
|
195965 | kd.successor(m_sk_packed_tuple_old, size2); |
| 12304 | } | ||
| 12305 | } else { | ||
| 12306 | 1684 | kd.get_supremum_key(m_sk_packed_tuple_old, &size2); | |
| 12307 | } | ||
| 12308 | |||
| 12309 | 198384 | const rocksdb::Slice slice1((const char *)m_sk_packed_tuple, size1); | |
| 12310 | 198384 | const rocksdb::Slice slice2((const char *)m_sk_packed_tuple_old, size2); | |
| 12311 | |||
| 12312 | // It's possible to get slice1 == slice2 for a non-inclusive range with the | ||
| 12313 | // right bound being successor() of the left one, e.g. "t.key>10 AND t.key<11" | ||
| 12314 |
3/4✓ Branch 0 taken 198384 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 198381 times.
|
198384 | if (slice1.compare(slice2) >= 0) { |
| 12315 | // It's not possible to get slice2 > slice1 | ||
| 12316 |
2/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
3 | assert(!min_key || !max_key || slice1.compare(slice2) == 0); |
| 12317 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_VOID_RETURN; |
| 12318 | } | ||
| 12319 | |||
| 12320 | 198381 | rocksdb::Range r(kd.m_is_reverse_cf ? slice2 : slice1, | |
| 12321 |
4/4✓ Branch 0 taken 121311 times.
✓ Branch 1 taken 77070 times.
✓ Branch 2 taken 121311 times.
✓ Branch 3 taken 77070 times.
|
198381 | kd.m_is_reverse_cf ? slice1 : slice2); |
| 12322 | |||
| 12323 | 198381 | uint64_t sz = 0; | |
| 12324 | |||
| 12325 | #pragma GCC diagnostic push | ||
| 12326 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||
| 12327 | // Getting statistics, including from Memtables | ||
| 12328 | 198381 | rocksdb::DB::SizeApproximationFlags include_flags = | |
| 12329 | rocksdb::DB::SizeApproximationFlags::INCLUDE_FILES; | ||
| 12330 |
1/2✓ Branch 0 taken 198381 times.
✗ Branch 1 not taken.
|
198381 | rdb->GetApproximateSizes(kd.get_cf(), &r, 1, &sz, include_flags); |
| 12331 | 198381 | *row_count = rows * ((double)sz / (double)disk_size); | |
| 12332 | 198381 | *total_size = sz; | |
| 12333 | uint64_t memTableCount; | ||
| 12334 |
1/2✓ Branch 0 taken 198381 times.
✗ Branch 1 not taken.
|
198381 | rdb->GetApproximateMemTableStats(kd.get_cf(), r, &memTableCount, &sz); |
| 12335 | 198381 | *row_count += memTableCount; | |
| 12336 | 198381 | *total_size += sz; | |
| 12337 |
1/2✓ Branch 0 taken 198381 times.
✗ Branch 1 not taken.
|
198381 | DBUG_VOID_RETURN; |
| 12338 | } | ||
| 12339 | |||
| 12340 | 2289 | void ha_rocksdb::update_create_info(HA_CREATE_INFO *const create_info) { | |
| 12341 |
1/2✓ Branch 0 taken 2289 times.
✗ Branch 1 not taken.
|
2289 | DBUG_ENTER_FUNC(); |
| 12342 | |||
| 12343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2289 times.
|
2289 | assert(create_info != nullptr); |
| 12344 | |||
| 12345 |
2/2✓ Branch 0 taken 2232 times.
✓ Branch 1 taken 57 times.
|
2289 | if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) { |
| 12346 | 2232 | create_info->auto_increment_value = m_tbl_def->m_auto_incr_val; | |
| 12347 | } | ||
| 12348 | |||
| 12349 |
1/2✓ Branch 0 taken 2289 times.
✗ Branch 1 not taken.
|
4578 | DBUG_VOID_RETURN; |
| 12350 | } | ||
| 12351 | |||
| 12352 | /** | ||
| 12353 | @brief | ||
| 12354 | Doing manual compaction on OPTIMIZE TABLE in RocksDB. | ||
| 12355 | Compaction itself is executed by background thread in RocksDB, but | ||
| 12356 | CompactRange() waits until compaction completes so this function | ||
| 12357 | may take a long time. | ||
| 12358 | Since RocksDB dataset is allocated per index id, OPTIMIZE TABLE | ||
| 12359 | triggers manual compaction for all indexes of the table. | ||
| 12360 | @details | ||
| 12361 | Compaction range is from the beginning of the index id to | ||
| 12362 | the first row of the next index id. When using reverse order | ||
| 12363 | column family, the first row of the next index id should be | ||
| 12364 | the last row of the previous index id. | ||
| 12365 | |||
| 12366 | @return | ||
| 12367 | HA_ADMIN_OK OK | ||
| 12368 | other HA_ADMIN error code | ||
| 12369 | */ | ||
| 12370 | 81 | int ha_rocksdb::optimize(THD *const thd, HA_CHECK_OPT *const check_opt) { | |
| 12371 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | DBUG_ENTER_FUNC(); |
| 12372 | |||
| 12373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
|
81 | assert(thd != nullptr); |
| 12374 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
|
81 | assert(check_opt != nullptr); |
| 12375 | |||
| 12376 |
2/2✓ Branch 0 taken 231 times.
✓ Branch 1 taken 78 times.
|
309 | for (uint i = 0; i < table->s->keys; i++) { |
| 12377 | uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]; | ||
| 12378 |
1/2✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
|
231 | auto range = get_range(i, buf); |
| 12379 | 231 | const rocksdb::Status s = rdb->CompactRange(getCompactRangeOptions(), | |
| 12380 | 231 | m_key_descr_arr[i]->get_cf(), | |
| 12381 |
1/2✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
|
462 | &range.start, &range.limit); |
| 12382 |
3/4✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 228 times.
|
231 | if (!s.ok()) { |
| 12383 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | DBUG_RETURN(rdb_error_to_mysql(s)); |
| 12384 | } | ||
| 12385 |
2/2✓ Branch 0 taken 228 times.
✓ Branch 1 taken 3 times.
|
231 | } |
| 12386 | |||
| 12387 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12388 | } | ||
| 12389 | |||
| 12390 | 908 | static void init_stats( | |
| 12391 | const std::unordered_map<GL_INDEX_ID, std::shared_ptr<const Rdb_key_def>> | ||
| 12392 | &to_recalc, | ||
| 12393 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> *stats) { | ||
| 12394 |
2/2✓ Branch 0 taken 2916 times.
✓ Branch 1 taken 907 times.
|
3823 | for (const auto &it : to_recalc) { |
| 12395 | 2916 | const GL_INDEX_ID index_id = it.first; | |
| 12396 | 2916 | auto &kd = it.second; | |
| 12397 | |||
| 12398 |
1/2✓ Branch 0 taken 2916 times.
✗ Branch 1 not taken.
|
2916 | (*stats).emplace(index_id, Rdb_index_stats(index_id)); |
| 12399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2916 times.
|
2916 | assert(kd->get_key_parts() > 0); |
| 12400 |
2/4✓ Branch 0 taken 2916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2915 times.
✗ Branch 3 not taken.
|
2916 | (*stats)[index_id].m_distinct_keys_per_prefix.resize(kd->get_key_parts()); |
| 12401 | } | ||
| 12402 | 907 | } | |
| 12403 | |||
| 12404 | /** | ||
| 12405 | Calculate the following index stats for all indexes of a table: | ||
| 12406 | number of rows, file size, and cardinality. It adopts an index | ||
| 12407 | scan approach using rocksdb::Iterator. Sampling is used to | ||
| 12408 | accelerate the scan. | ||
| 12409 | **/ | ||
| 12410 | 442 | static int calculate_cardinality_table_scan( | |
| 12411 | const std::unordered_map<GL_INDEX_ID, std::shared_ptr<const Rdb_key_def>> | ||
| 12412 | &to_recalc, | ||
| 12413 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> *stats, | ||
| 12414 | table_cardinality_scan_type scan_type, uint64_t max_num_rows_scanned, | ||
| 12415 | std::atomic<THD::killed_state> *killed) { | ||
| 12416 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | DBUG_ENTER_FUNC(); |
| 12417 | |||
| 12418 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
|
442 | assert(scan_type != SCAN_TYPE_NONE); |
| 12419 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | init_stats(to_recalc, stats); |
| 12420 | |||
| 12421 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | auto read_opts = rocksdb::ReadOptions(); |
| 12422 | 442 | read_opts.fill_cache = false; | |
| 12423 |
2/2✓ Branch 0 taken 393 times.
✓ Branch 1 taken 49 times.
|
442 | if (scan_type == SCAN_TYPE_MEMTABLE_ONLY) { |
| 12424 | 393 | read_opts.read_tier = rocksdb::ReadTier::kMemtableTier; | |
| 12425 | } else { | ||
| 12426 | 49 | read_opts.total_order_seek = true; | |
| 12427 | } | ||
| 12428 | |||
| 12429 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | Rdb_tbl_card_coll cardinality_collector(rocksdb_table_stats_sampling_pct); |
| 12430 | |||
| 12431 |
2/2✓ Branch 0 taken 1425 times.
✓ Branch 1 taken 442 times.
|
1867 | for (const auto &it_kd : to_recalc) { |
| 12432 | 1425 | const GL_INDEX_ID index_id = it_kd.first; | |
| 12433 | |||
| 12434 |
2/4✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1425 times.
|
1425 | if (!ddl_manager.safe_find(index_id)) { |
| 12435 | // If index id is not in ddl manager, then it has been dropped. | ||
| 12436 | // Skip scanning index | ||
| 12437 | ✗ | continue; | |
| 12438 | } | ||
| 12439 | |||
| 12440 | 1425 | const std::shared_ptr<const Rdb_key_def> &kd = it_kd.second; | |
| 12441 |
2/4✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1425 times.
|
1425 | assert(index_id == kd->get_gl_index_id()); |
| 12442 |
2/4✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1425 times.
✗ Branch 3 not taken.
|
1425 | Rdb_index_stats &stat = (*stats)[kd->get_gl_index_id()]; |
| 12443 | |||
| 12444 | uchar r_buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]; | ||
| 12445 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | auto r = ha_rocksdb::get_range(*kd, r_buf); |
| 12446 | uint64_t memtableCount; | ||
| 12447 | uint64_t memtableSize; | ||
| 12448 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | rdb->GetApproximateMemTableStats(kd->get_cf(), r, &memtableCount, |
| 12449 | &memtableSize); | ||
| 12450 | |||
| 12451 |
2/2✓ Branch 0 taken 1206 times.
✓ Branch 1 taken 219 times.
|
1425 | if (scan_type == SCAN_TYPE_MEMTABLE_ONLY && |
| 12452 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1206 times.
|
1206 | memtableCount < (uint64_t)stat.m_rows / 10) { |
| 12453 | // skip tables that already have enough stats from SST files to reduce | ||
| 12454 | // overhead and avoid degradation of big tables stats by sampling from | ||
| 12455 | // relatively tiny (less than 10% of full data set) memtable dataset | ||
| 12456 | ✗ | continue; | |
| 12457 | } | ||
| 12458 | |||
| 12459 | // Set memtable count to row count | ||
| 12460 | 1425 | stat.m_rows = memtableCount; | |
| 12461 | |||
| 12462 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 1206 times.
|
1425 | if (scan_type == SCAN_TYPE_FULL_TABLE) { |
| 12463 | // Set memtable size to file size | ||
| 12464 | 219 | stat.m_actual_disk_size = memtableSize; | |
| 12465 | } | ||
| 12466 | |||
| 12467 | std::unique_ptr<rocksdb::Iterator> it = std::unique_ptr<rocksdb::Iterator>( | ||
| 12468 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | rdb->NewIterator(read_opts, kd->get_cf())); |
| 12469 | rocksdb::Slice first_index_key((const char *)r_buf, | ||
| 12470 | 1425 | Rdb_key_def::INDEX_NUMBER_SIZE); | |
| 12471 | |||
| 12472 | // Reset m_last_key for new index | ||
| 12473 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | cardinality_collector.Reset(); |
| 12474 | 1425 | uint64_t rows_scanned = 0ul; | |
| 12475 |
5/8✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10458395 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10459820 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10458696 times.
✓ Branch 7 taken 1124 times.
|
10459819 | for (it->Seek(first_index_key); is_valid_iterator(it.get()); it->Next()) { |
| 12476 |
3/6✓ Branch 0 taken 10458696 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10458696 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10458696 times.
|
10458696 | if (killed && *killed) { |
| 12477 | ✗ | LogPluginErrMsg( | |
| 12478 | INFORMATION_LEVEL, 0, | ||
| 12479 | "Index stats calculation for index %s with id (%u,%u) is " | ||
| 12480 | "terminated", | ||
| 12481 | kd->get_name().c_str(), stat.m_gl_index_id.cf_id, | ||
| 12482 | stat.m_gl_index_id.index_id); | ||
| 12483 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 12484 | } | ||
| 12485 | |||
| 12486 |
1/2✓ Branch 0 taken 10458696 times.
✗ Branch 1 not taken.
|
10458696 | const rocksdb::Slice key = it->key(); |
| 12487 | |||
| 12488 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 692784 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
692784 | if ((scan_type == SCAN_TYPE_FULL_TABLE && max_num_rows_scanned > 0 && |
| 12489 |
4/4✓ Branch 0 taken 692784 times.
✓ Branch 1 taken 9765912 times.
✓ Branch 2 taken 301 times.
✓ Branch 3 taken 10458395 times.
|
20917392 | rows_scanned >= max_num_rows_scanned) || |
| 12490 |
2/2✓ Branch 0 taken 301 times.
✓ Branch 1 taken 10458395 times.
|
10458696 | !kd->covers_key(key)) { |
| 12491 | 301 | break; // end of this index | |
| 12492 | } | ||
| 12493 | |||
| 12494 |
1/2✓ Branch 0 taken 10458394 times.
✗ Branch 1 not taken.
|
10458395 | cardinality_collector.ProcessKey(key, kd.get(), &stat); |
| 12495 | 10458394 | rows_scanned++; | |
| 12496 | } | ||
| 12497 | |||
| 12498 | cardinality_collector | ||
| 12499 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | .Reset(); /* reset m_last_key for each key definition */ |
| 12500 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | cardinality_collector.SetCardinality(&stat); |
| 12501 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | cardinality_collector.AdjustStats(&stat); |
| 12502 | |||
| 12503 |
12/20✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1419 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
|
1425 | DBUG_EXECUTE_IF("rocksdb_calculate_stats", { |
| 12504 | if (kd->get_name() == "secondary_key") { | ||
| 12505 | THD *thd = new THD(); | ||
| 12506 | thd->thread_stack = reinterpret_cast<char *>(&thd); | ||
| 12507 | thd->store_globals(); | ||
| 12508 | |||
| 12509 | static constexpr char act[] = | ||
| 12510 | "now signal ready_to_drop_index wait_for ready_to_save_index_stats"; | ||
| 12511 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 12512 | |||
| 12513 | thd->restore_globals(); | ||
| 12514 | delete thd; | ||
| 12515 | } | ||
| 12516 | }); | ||
| 12517 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | } |
| 12518 | |||
| 12519 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12520 | 442 | } | |
| 12521 | |||
| 12522 | 49 | static void reset_cardinality( | |
| 12523 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> *stats) { | ||
| 12524 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 49 times.
|
268 | for (auto &src : *stats) { |
| 12525 | 219 | Rdb_index_stats &stat = src.second; | |
| 12526 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | stat.reset_cardinality(); |
| 12527 | } | ||
| 12528 | 49 | } | |
| 12529 | |||
| 12530 | 442 | static void merge_stats( | |
| 12531 | const std::unordered_map<GL_INDEX_ID, std::shared_ptr<const Rdb_key_def>> | ||
| 12532 | &to_recalc, | ||
| 12533 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> *stats, | ||
| 12534 | const std::unordered_map<GL_INDEX_ID, Rdb_index_stats> &card_stats) { | ||
| 12535 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
|
442 | assert(stats->size() == card_stats.size()); |
| 12536 | |||
| 12537 |
2/2✓ Branch 0 taken 1425 times.
✓ Branch 1 taken 442 times.
|
1867 | for (auto &src : *stats) { |
| 12538 | 1425 | auto index_id = src.first; | |
| 12539 | 1425 | Rdb_index_stats &stat = src.second; | |
| 12540 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | auto it = card_stats.find(index_id); |
| 12541 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1425 times.
|
1425 | assert(it != card_stats.end()); |
| 12542 | |||
| 12543 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | auto it_index = to_recalc.find(index_id); |
| 12544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1425 times.
|
1425 | assert(it_index != to_recalc.end()); |
| 12545 |
1/2✓ Branch 0 taken 1425 times.
✗ Branch 1 not taken.
|
1425 | stat.merge(it->second, true, it_index->second->max_storage_fmt_length()); |
| 12546 | } | ||
| 12547 | 442 | } | |
| 12548 | |||
| 12549 | ✗ | static void adjust_cardinality( | |
| 12550 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> *stats, | ||
| 12551 | table_cardinality_scan_type scan_type, uint64_t max_num_rows_scanned) { | ||
| 12552 | ✗ | assert(scan_type == SCAN_TYPE_FULL_TABLE); | |
| 12553 | ✗ | assert(max_num_rows_scanned > 0); | |
| 12554 | |||
| 12555 | ✗ | for (auto &src : *stats) { | |
| 12556 | ✗ | Rdb_index_stats &stat = src.second; | |
| 12557 | ✗ | if ((uint64_t)stat.m_rows > max_num_rows_scanned) { | |
| 12558 | ✗ | stat.adjust_cardinality(stat.m_rows / max_num_rows_scanned); | |
| 12559 | } | ||
| 12560 | #ifndef NDEBUG | ||
| 12561 | ✗ | for (size_t i = 0; i < stat.m_distinct_keys_per_prefix.size(); i++) { | |
| 12562 | ✗ | assert(stat.m_distinct_keys_per_prefix[i] <= stat.m_rows); | |
| 12563 | } | ||
| 12564 | #endif | ||
| 12565 | } | ||
| 12566 | } | ||
| 12567 | |||
| 12568 | 466 | static int read_stats_from_ssts( | |
| 12569 | const std::unordered_map<GL_INDEX_ID, std::shared_ptr<const Rdb_key_def>> | ||
| 12570 | &to_recalc, | ||
| 12571 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> *stats) { | ||
| 12572 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | DBUG_ENTER_FUNC(); |
| 12573 | |||
| 12574 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | init_stats(to_recalc, stats); |
| 12575 | |||
| 12576 | // find per column family key ranges which need to be queried | ||
| 12577 | std::unordered_map<rocksdb::ColumnFamilyHandle *, std::vector<rocksdb::Range>> | ||
| 12578 | 466 | ranges; | |
| 12579 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | std::vector<uchar> buf(to_recalc.size() * 2 * Rdb_key_def::INDEX_NUMBER_SIZE); |
| 12580 | |||
| 12581 | 466 | uchar *bufp = buf.data(); | |
| 12582 |
2/2✓ Branch 0 taken 1491 times.
✓ Branch 1 taken 466 times.
|
1957 | for (const auto &it : to_recalc) { |
| 12583 | 1491 | auto &kd = it.second; | |
| 12584 |
3/6✓ Branch 0 taken 1491 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1491 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1491 times.
✗ Branch 5 not taken.
|
1491 | ranges[kd->get_cf()].push_back(ha_rocksdb::get_range(*kd, bufp)); |
| 12585 | 1491 | bufp += 2 * Rdb_key_def::INDEX_NUMBER_SIZE; | |
| 12586 | } | ||
| 12587 | |||
| 12588 | // get RocksDB table properties for these ranges | ||
| 12589 | 466 | rocksdb::TablePropertiesCollection props; | |
| 12590 |
2/2✓ Branch 0 taken 505 times.
✓ Branch 1 taken 466 times.
|
971 | for (const auto &it : ranges) { |
| 12591 | 505 | const auto old_size MY_ATTRIBUTE((__unused__)) = props.size(); | |
| 12592 | 505 | const auto status = rdb->GetPropertiesOfTablesInRange( | |
| 12593 |
1/2✓ Branch 0 taken 505 times.
✗ Branch 1 not taken.
|
505 | it.first, &it.second[0], it.second.size(), &props); |
| 12594 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
505 | assert(props.size() >= old_size); |
| 12595 |
2/4✓ Branch 0 taken 505 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 505 times.
|
505 | if (!status.ok()) { |
| 12596 | ✗ | DBUG_RETURN(ha_rocksdb::rdb_error_to_mysql( | |
| 12597 | status, "Could not access RocksDB properties")); | ||
| 12598 | } | ||
| 12599 |
1/2✓ Branch 0 taken 505 times.
✗ Branch 1 not taken.
|
505 | } |
| 12600 | |||
| 12601 | 466 | int num_sst = 0; | |
| 12602 |
2/2✓ Branch 0 taken 1116 times.
✓ Branch 1 taken 466 times.
|
1582 | for (const auto &it : props) { |
| 12603 | 1116 | std::vector<Rdb_index_stats> sst_stats; | |
| 12604 |
1/2✓ Branch 0 taken 1116 times.
✗ Branch 1 not taken.
|
1116 | Rdb_tbl_prop_coll::read_stats_from_tbl_props(it.second, &sst_stats); |
| 12605 | /* | ||
| 12606 | sst_stats is a list of index statistics for indexes that have entries | ||
| 12607 | in the current SST file. | ||
| 12608 | */ | ||
| 12609 |
2/2✓ Branch 0 taken 20501 times.
✓ Branch 1 taken 1116 times.
|
21617 | for (const auto &it1 : sst_stats) { |
| 12610 | /* | ||
| 12611 | Only update statistics for indexes that belong to this SQL table. | ||
| 12612 | |||
| 12613 | The reason is: We are walking through all SST files that have | ||
| 12614 | entries from this table (and so can compute good statistics). For | ||
| 12615 | other SQL tables, it can be that we're only seeing a small fraction | ||
| 12616 | of table's entries (and so we can't update statistics based on that). | ||
| 12617 | */ | ||
| 12618 |
3/4✓ Branch 0 taken 20501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17373 times.
✓ Branch 3 taken 3128 times.
|
20501 | if (stats->find(it1.m_gl_index_id) == stats->end()) { |
| 12619 | 17373 | continue; | |
| 12620 | } | ||
| 12621 | |||
| 12622 |
1/2✓ Branch 0 taken 3128 times.
✗ Branch 1 not taken.
|
3128 | auto it_index = to_recalc.find(it1.m_gl_index_id); |
| 12623 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3128 times.
|
3128 | assert(it_index != to_recalc.end()); |
| 12624 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3128 times.
|
3128 | if (it_index == to_recalc.end()) { |
| 12625 | ✗ | continue; | |
| 12626 | } | ||
| 12627 | |||
| 12628 |
2/4✓ Branch 0 taken 3128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3128 times.
✗ Branch 3 not taken.
|
6256 | (*stats)[it1.m_gl_index_id].merge( |
| 12629 | 3128 | it1, true, it_index->second->max_storage_fmt_length()); | |
| 12630 | } | ||
| 12631 | 1116 | num_sst++; | |
| 12632 | 1116 | } | |
| 12633 | |||
| 12634 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12635 | 466 | } | |
| 12636 | |||
| 12637 | 466 | static int calculate_stats( | |
| 12638 | const std::unordered_map<GL_INDEX_ID, std::shared_ptr<const Rdb_key_def>> | ||
| 12639 | &to_recalc, | ||
| 12640 | table_cardinality_scan_type scan_type, | ||
| 12641 | std::atomic<THD::killed_state> *killed) { | ||
| 12642 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | DBUG_ENTER_FUNC(); |
| 12643 | |||
| 12644 | 466 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> stats; | |
| 12645 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | int ret = read_stats_from_ssts(to_recalc, &stats); |
| 12646 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
|
466 | if (ret != HA_EXIT_SUCCESS) { |
| 12647 | ✗ | DBUG_RETURN(ret); | |
| 12648 | } | ||
| 12649 | |||
| 12650 |
2/2✓ Branch 0 taken 442 times.
✓ Branch 1 taken 24 times.
|
466 | if (scan_type != SCAN_TYPE_NONE) { |
| 12651 | 442 | std::unordered_map<GL_INDEX_ID, Rdb_index_stats> card_stats; | |
| 12652 | 442 | uint64_t max_num_rows_scanned = rocksdb_table_stats_max_num_rows_scanned; | |
| 12653 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | ret = calculate_cardinality_table_scan(to_recalc, &card_stats, scan_type, |
| 12654 | max_num_rows_scanned, killed); | ||
| 12655 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
|
442 | if (ret != HA_EXIT_SUCCESS) { |
| 12656 | ✗ | DBUG_RETURN(ret); | |
| 12657 | } | ||
| 12658 | |||
| 12659 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 393 times.
|
442 | if (scan_type == SCAN_TYPE_FULL_TABLE) { |
| 12660 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | reset_cardinality(&stats); |
| 12661 | } | ||
| 12662 | |||
| 12663 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | merge_stats(to_recalc, &stats, card_stats); |
| 12664 |
3/4✓ Branch 0 taken 49 times.
✓ Branch 1 taken 393 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
|
442 | if (scan_type == SCAN_TYPE_FULL_TABLE && max_num_rows_scanned > 0) { |
| 12665 | ✗ | adjust_cardinality(&stats, scan_type, max_num_rows_scanned); | |
| 12666 | } | ||
| 12667 |
1/2✓ Branch 0 taken 442 times.
✗ Branch 1 not taken.
|
442 | } |
| 12668 | |||
| 12669 | // set and persist new stats | ||
| 12670 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | ddl_manager.set_stats(stats); |
| 12671 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | ddl_manager.persist_stats(true); |
| 12672 | |||
| 12673 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12674 | 466 | } | |
| 12675 | |||
| 12676 | 466 | static int calculate_stats_for_table( | |
| 12677 | const std::string &tbl_name, table_cardinality_scan_type scan_type, | ||
| 12678 | std::atomic<THD::killed_state> *killed = nullptr) { | ||
| 12679 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | DBUG_ENTER_FUNC(); |
| 12680 | 466 | std::unordered_map<GL_INDEX_ID, std::shared_ptr<const Rdb_key_def>> to_recalc; | |
| 12681 | 466 | std::vector<GL_INDEX_ID> indexes; | |
| 12682 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | ddl_manager.find_indexes(tbl_name, &indexes); |
| 12683 | |||
| 12684 |
2/2✓ Branch 0 taken 1491 times.
✓ Branch 1 taken 466 times.
|
1957 | for (const auto &index : indexes) { |
| 12685 |
1/2✓ Branch 0 taken 1491 times.
✗ Branch 1 not taken.
|
1491 | std::shared_ptr<const Rdb_key_def> keydef = ddl_manager.safe_find(index); |
| 12686 | |||
| 12687 |
1/2✓ Branch 0 taken 1491 times.
✗ Branch 1 not taken.
|
1491 | if (keydef) { |
| 12688 |
3/6✓ Branch 0 taken 1491 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1491 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1491 times.
✗ Branch 5 not taken.
|
1491 | to_recalc.insert(std::make_pair(keydef->get_gl_index_id(), keydef)); |
| 12689 | } | ||
| 12690 | 1491 | } | |
| 12691 | |||
| 12692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
|
466 | if (to_recalc.empty()) { |
| 12693 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 12694 | } | ||
| 12695 | |||
| 12696 |
11/20✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 463 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
|
466 | DBUG_EXECUTE_IF("rocksdb_is_bg_thread_drop_table", { |
| 12697 | if (tbl_name == "test.t") { | ||
| 12698 | THD *thd = new THD(); | ||
| 12699 | thd->thread_stack = reinterpret_cast<char *>(&thd); | ||
| 12700 | thd->store_globals(); | ||
| 12701 | |||
| 12702 | static constexpr char act[] = "now signal ready_to_drop_table"; | ||
| 12703 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 12704 | |||
| 12705 | thd->restore_globals(); | ||
| 12706 | delete thd; | ||
| 12707 | } | ||
| 12708 | }); | ||
| 12709 | |||
| 12710 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | int err = calculate_stats(to_recalc, scan_type, killed); |
| 12711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
|
466 | if (err != HA_EXIT_SUCCESS) { |
| 12712 | ✗ | DBUG_RETURN(err); | |
| 12713 | } | ||
| 12714 | |||
| 12715 |
11/20✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 463 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
|
466 | DBUG_EXECUTE_IF("rocksdb_is_bg_thread_drop_table", { |
| 12716 | if (tbl_name == "test.t") { | ||
| 12717 | THD *thd = new THD(); | ||
| 12718 | thd->thread_stack = reinterpret_cast<char *>(&thd); | ||
| 12719 | thd->store_globals(); | ||
| 12720 | |||
| 12721 | static constexpr char act[] = "now wait_for ready_to_save_table_stats"; | ||
| 12722 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 12723 | |||
| 12724 | thd->restore_globals(); | ||
| 12725 | delete thd; | ||
| 12726 | } | ||
| 12727 | }); | ||
| 12728 | |||
| 12729 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 417 times.
|
466 | if (scan_type == SCAN_TYPE_FULL_TABLE) { |
| 12730 | // Save table stats including number of rows | ||
| 12731 | // and modified counter | ||
| 12732 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | ddl_manager.set_table_stats(tbl_name); |
| 12733 | } | ||
| 12734 | |||
| 12735 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12736 | 466 | } | |
| 12737 | |||
| 12738 | /* | ||
| 12739 | @return | ||
| 12740 | HA_ADMIN_OK OK | ||
| 12741 | other HA_ADMIN error code | ||
| 12742 | */ | ||
| 12743 | 405 | int ha_rocksdb::analyze(THD *const thd, HA_CHECK_OPT *const check_opt) { | |
| 12744 |
1/2✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
|
405 | DBUG_ENTER_FUNC(); |
| 12745 | |||
| 12746 |
1/2✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
|
405 | if (table) { |
| 12747 | 405 | table_cardinality_scan_type scan_type = rocksdb_table_stats_use_table_scan | |
| 12748 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 393 times.
|
405 | ? SCAN_TYPE_FULL_TABLE |
| 12749 | : SCAN_TYPE_MEMTABLE_ONLY; | ||
| 12750 | |||
| 12751 |
1/2✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
|
405 | if (calculate_stats_for_table(m_tbl_def->full_tablename(), scan_type, |
| 12752 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 405 times.
|
405 | &(thd->killed)) != HA_EXIT_SUCCESS) { |
| 12753 | ✗ | DBUG_RETURN(HA_ADMIN_FAILED); | |
| 12754 | } | ||
| 12755 | } | ||
| 12756 | |||
| 12757 |
1/2✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
|
405 | DBUG_RETURN(HA_ADMIN_OK); |
| 12758 | } | ||
| 12759 | |||
| 12760 | 463014 | int ha_rocksdb::adjust_handler_stats_sst_and_memtable(ha_statistics *ha_stats, | |
| 12761 | Rdb_tbl_def *tbl_def) { | ||
| 12762 |
1/2✓ Branch 0 taken 463015 times.
✗ Branch 1 not taken.
|
463014 | DBUG_ENTER_FUNC(); |
| 12763 | |||
| 12764 | /* | ||
| 12765 | If any stats are negative due to bad cached stats, re-run analyze table | ||
| 12766 | and re-retrieve the stats. | ||
| 12767 | */ | ||
| 12768 |
2/2✓ Branch 0 taken 463001 times.
✓ Branch 1 taken 14 times.
|
463015 | if (static_cast<longlong>(ha_stats->data_file_length) < 0 || |
| 12769 |
2/2✓ Branch 0 taken 462992 times.
✓ Branch 1 taken 9 times.
|
463001 | static_cast<longlong>(ha_stats->index_file_length) < 0 || |
| 12770 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 462992 times.
|
462992 | static_cast<longlong>(ha_stats->records) < 0) { |
| 12771 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
|
23 | if (calculate_stats_for_table(tbl_def->full_tablename(), SCAN_TYPE_NONE)) { |
| 12772 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 12773 | } | ||
| 12774 | |||
| 12775 | 24 | rocksdb_get_stats(ha_stats, tbl_def); | |
| 12776 | } | ||
| 12777 | |||
| 12778 | // if number of records is hardcoded, we do not want to force computation | ||
| 12779 | // of memtable cardinalities | ||
| 12780 |
4/4✓ Branch 0 taken 330129 times.
✓ Branch 1 taken 132887 times.
✓ Branch 2 taken 330128 times.
✓ Branch 3 taken 1 times.
|
463016 | if (ha_stats->records == 0 || (rocksdb_force_compute_memtable_stats && |
| 12781 |
2/2✓ Branch 0 taken 313264 times.
✓ Branch 1 taken 16864 times.
|
330128 | rocksdb_debug_optimizer_n_rows == 0)) { |
| 12782 | // First, compute SST files stats | ||
| 12783 | uchar buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]; | ||
| 12784 | 446151 | std::shared_ptr<Rdb_key_def> pk_def = tbl_def->get_pk_def(); | |
| 12785 |
1/2✓ Branch 0 taken 446150 times.
✗ Branch 1 not taken.
|
446151 | auto r = ha_rocksdb::get_range(*pk_def, buf); |
| 12786 | 446150 | uint64_t sz = 0; | |
| 12787 | |||
| 12788 | 446150 | rocksdb::DB::SizeApproximationFlags include_flags = | |
| 12789 | rocksdb::DB::SizeApproximationFlags::INCLUDE_FILES; | ||
| 12790 | |||
| 12791 | // recompute SST files stats only if records count is 0 | ||
| 12792 |
2/2✓ Branch 0 taken 132886 times.
✓ Branch 1 taken 313264 times.
|
446150 | if (ha_stats->records == 0) { |
| 12793 |
1/2✓ Branch 0 taken 132884 times.
✗ Branch 1 not taken.
|
132886 | rdb->GetApproximateSizes(pk_def->get_cf(), &r, 1, &sz, include_flags); |
| 12794 | 132886 | ha_stats->records += sz / ROCKSDB_ASSUMED_KEY_VALUE_DISK_SIZE; | |
| 12795 | 132886 | ha_stats->data_file_length += sz; | |
| 12796 | } | ||
| 12797 | |||
| 12798 | // Second, compute memtable stats. This call is expensive, so cache | ||
| 12799 | // values computed for some time. | ||
| 12800 | 446150 | uint64_t cachetime = rocksdb_force_compute_memtable_stats_cachetime; | |
| 12801 |
2/2✓ Branch 0 taken 32192 times.
✓ Branch 1 taken 413958 times.
|
446150 | uint64_t time = (cachetime == 0) ? 0 : my_micro_time(); |
| 12802 |
4/4✓ Branch 0 taken 32192 times.
✓ Branch 1 taken 413958 times.
✓ Branch 2 taken 4894 times.
✓ Branch 3 taken 27298 times.
|
446150 | if (cachetime == 0 || time > tbl_def->m_mtcache_last_update + cachetime) { |
| 12803 | uint64_t memtableCount; | ||
| 12804 | uint64_t memtableSize; | ||
| 12805 | |||
| 12806 | // the stats below are calculated from skiplist wich is a probablistic | ||
| 12807 | // data structure, so the results vary between test runs | ||
| 12808 | // it also can return 0 for quite a large tables which means that | ||
| 12809 | // cardinality for memtable only indxes will be reported as 0 | ||
| 12810 | |||
| 12811 |
1/2✓ Branch 0 taken 418851 times.
✗ Branch 1 not taken.
|
418852 | rdb->GetApproximateMemTableStats(pk_def->get_cf(), r, &memtableCount, |
| 12812 | &memtableSize); | ||
| 12813 | |||
| 12814 | // Atomically update all of these fields at the same time | ||
| 12815 |
2/2✓ Branch 0 taken 4894 times.
✓ Branch 1 taken 413957 times.
|
418851 | if (cachetime > 0) { |
| 12816 |
1/2✓ Branch 0 taken 4894 times.
✗ Branch 1 not taken.
|
9788 | if (tbl_def->m_mtcache_lock.fetch_add(1, std::memory_order_acquire) == |
| 12817 | 0) { | ||
| 12818 | 4894 | tbl_def->m_mtcache_count = memtableCount; | |
| 12819 | 4894 | tbl_def->m_mtcache_size = memtableSize; | |
| 12820 | 4894 | tbl_def->m_mtcache_last_update = time; | |
| 12821 | } | ||
| 12822 | 4894 | tbl_def->m_mtcache_lock.fetch_sub(1, std::memory_order_release); | |
| 12823 | } | ||
| 12824 | |||
| 12825 | 418851 | ha_stats->records += memtableCount; | |
| 12826 | 418851 | ha_stats->data_file_length += memtableSize; | |
| 12827 | 418851 | } else { | |
| 12828 | // Cached data is still valid, so use it instead | ||
| 12829 | 27298 | ha_stats->records += tbl_def->m_mtcache_count; | |
| 12830 | 27298 | ha_stats->data_file_length += tbl_def->m_mtcache_size; | |
| 12831 | } | ||
| 12832 | 446149 | } | |
| 12833 | |||
| 12834 |
1/2✓ Branch 0 taken 463015 times.
✗ Branch 1 not taken.
|
463015 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 12835 | } | ||
| 12836 | |||
| 12837 | 6625450 | void ha_rocksdb::get_auto_increment(ulonglong off, ulonglong inc, | |
| 12838 | ulonglong nb_desired_values, | ||
| 12839 | ulonglong *const first_value, | ||
| 12840 | ulonglong *const nb_reserved_values) { | ||
| 12841 | /* | ||
| 12842 | MySQL has a somewhat complicated way of handling the auto-increment value. | ||
| 12843 | The first time get_auto_increment is called for a statement, | ||
| 12844 | nb_desired_values is the estimate for how many values will be needed. The | ||
| 12845 | engine can then reserve some values, and those will be automatically used | ||
| 12846 | by MySQL, until a hard-coded value shows up in the insert statement, after | ||
| 12847 | which MySQL again calls this function to reset its starting value. | ||
| 12848 | * | ||
| 12849 | For simplicity we will just ignore nb_desired_values - we aren't going to | ||
| 12850 | reserve any extra values for a multi-insert statement. Each row will | ||
| 12851 | simply acquire the next value as needed and we will always tell MySQL that | ||
| 12852 | we only reserved 1 value. Since we are using an atomic value for | ||
| 12853 | m_auto_incr_val this should be safe - if we had to grab a mutex, doing | ||
| 12854 | an actual reserve of some values might be a better solution. | ||
| 12855 | */ | ||
| 12856 |
3/6✓ Branch 0 taken 6687311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6700487 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6730244 times.
✗ Branch 5 not taken.
|
6625450 | DEBUG_SYNC(ha_thd(), "rocksdb.autoinc_vars"); |
| 12857 | |||
| 12858 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6705605 times.
|
6705623 | if (off > inc) { |
| 12859 | 18 | off = 1; | |
| 12860 | } | ||
| 12861 | |||
| 12862 | Field *field; | ||
| 12863 | ulonglong new_val, max_val; | ||
| 12864 | 6705623 | field = table->key_info[table->s->next_number_index].key_part[0].field; | |
| 12865 |
1/2✓ Branch 0 taken 6678766 times.
✗ Branch 1 not taken.
|
6705623 | max_val = rdb_get_int_col_max_value(field); |
| 12866 | |||
| 12867 | // Local variable reference to simplify code below | ||
| 12868 | 6678766 | auto &auto_incr = m_tbl_def->m_auto_incr_val; | |
| 12869 | |||
| 12870 |
2/2✓ Branch 0 taken 3745683 times.
✓ Branch 1 taken 2933083 times.
|
6678766 | if (inc == 1) { |
| 12871 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3745683 times.
|
3745683 | assert(off == 1); |
| 12872 | // Optimization for the standard case where we are always simply | ||
| 12873 | // incrementing from the last position | ||
| 12874 | |||
| 12875 | // Use CAS operation in a loop to make sure automically get the next auto | ||
| 12876 | // increment value while ensuring that we don't wrap around to a negative | ||
| 12877 | // number. | ||
| 12878 | // | ||
| 12879 | // We set auto_incr to the min of max_val and new_val + 1. This means that | ||
| 12880 | // if we're at the maximum, we should be returning the same value for | ||
| 12881 | // multiple rows, resulting in duplicate key errors (as expected). | ||
| 12882 | // | ||
| 12883 | // If we return values greater than the max, the SQL layer will "truncate" | ||
| 12884 | // the value anyway, but it means that we store invalid values into | ||
| 12885 | // auto_incr that will be visible in SHOW CREATE TABLE. | ||
| 12886 | 3745683 | new_val = auto_incr; | |
| 12887 |
2/2✓ Branch 0 taken 3746059 times.
✓ Branch 1 taken 3 times.
|
3746114 | while (new_val != std::numeric_limits<ulonglong>::max()) { |
| 12888 | 3746026 | if (auto_incr.compare_exchange_weak(new_val, | |
| 12889 |
2/2✓ Branch 0 taken 3745891 times.
✓ Branch 1 taken 645 times.
|
7492595 | std::min(new_val + 1, max_val))) { |
| 12890 | 3745891 | break; | |
| 12891 | } | ||
| 12892 | } | ||
| 12893 | } else { | ||
| 12894 | // The next value can be more complicated if either 'inc' or 'off' is not 1 | ||
| 12895 | 2933083 | ulonglong last_val = auto_incr; | |
| 12896 | |||
| 12897 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2924946 times.
|
2924952 | if (last_val > max_val) { |
| 12898 | 6 | new_val = std::numeric_limits<ulonglong>::max(); | |
| 12899 | } else { | ||
| 12900 | // Loop until we can correctly update the atomic value | ||
| 12901 | do { | ||
| 12902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3090472 times.
|
3090472 | assert(last_val > 0); |
| 12903 | // Calculate the next value in the auto increment series: offset | ||
| 12904 | // + N * increment where N is 0, 1, 2, ... | ||
| 12905 | // | ||
| 12906 | // For further information please visit: | ||
| 12907 | // http://dev.mysql.com/doc/refman/5.7/en/replication-options-master.html | ||
| 12908 | // | ||
| 12909 | // The following is confusing so here is an explanation: | ||
| 12910 | // To get the next number in the sequence above you subtract out the | ||
| 12911 | // offset, calculate the next sequence (N * increment) and then add the | ||
| 12912 | // offset back in. | ||
| 12913 | // | ||
| 12914 | // The additions are rearranged to avoid overflow. The following is | ||
| 12915 | // equivalent to (last_val - 1 + inc - off) / inc. This uses the fact | ||
| 12916 | // that (a+b)/c = a/c + b/c + (a%c + b%c)/c. To show why: | ||
| 12917 | // | ||
| 12918 | // (a+b)/c | ||
| 12919 | // = (a - a%c + a%c + b - b%c + b%c) / c | ||
| 12920 | // = (a - a%c) / c + (b - b%c) / c + (a%c + b%c) / c | ||
| 12921 | // = a/c + b/c + (a%c + b%c) / c | ||
| 12922 | // | ||
| 12923 | // Now, substitute a = last_val - 1, b = inc - off, c = inc to get the | ||
| 12924 | // following statement. | ||
| 12925 | 3090472 | ulonglong n = | |
| 12926 | 3090472 | (last_val - 1) / inc + ((last_val - 1) % inc + inc - off) / inc; | |
| 12927 | |||
| 12928 | // Check if n * inc + off will overflow. This can only happen if we have | ||
| 12929 | // an UNSIGNED BIGINT field. | ||
| 12930 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3059975 times.
|
3090472 | if (n > (std::numeric_limits<ulonglong>::max() - off) / inc) { |
| 12931 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | assert(max_val == std::numeric_limits<ulonglong>::max()); |
| 12932 | // The 'last_val' value is already equal to or larger than the largest | ||
| 12933 | // value in the sequence. Continuing would wrap around (technically | ||
| 12934 | // the behavior would be undefined). What should we do? | ||
| 12935 | // We could: | ||
| 12936 | // 1) set the new value to the last possible number in our sequence | ||
| 12937 | // as described above. The problem with this is that this | ||
| 12938 | // number could be smaller than a value in an existing row. | ||
| 12939 | // 2) set the new value to the largest possible number. This number | ||
| 12940 | // may not be in our sequence, but it is guaranteed to be equal | ||
| 12941 | // to or larger than any other value already inserted. | ||
| 12942 | // | ||
| 12943 | // For now I'm going to take option 2. | ||
| 12944 | // | ||
| 12945 | // Returning ULLONG_MAX from get_auto_increment will cause the SQL | ||
| 12946 | // layer to fail with ER_AUTOINC_READ_FAILED. This means that due to | ||
| 12947 | // the SE API for get_auto_increment, inserts will fail with | ||
| 12948 | // ER_AUTOINC_READ_FAILED if the column is UNSIGNED BIGINT, but | ||
| 12949 | // inserts will fail with ER_DUP_ENTRY for other types (or no failure | ||
| 12950 | // if the column is in a non-unique SK). | ||
| 12951 | 12 | new_val = std::numeric_limits<ulonglong>::max(); | |
| 12952 | 12 | auto_incr = new_val; // Store the largest value into auto_incr | |
| 12953 | 13084 | break; | |
| 12954 | } | ||
| 12955 | |||
| 12956 | 3059975 | new_val = n * inc + off; | |
| 12957 | |||
| 12958 | // Attempt to store the new value (plus 1 since m_auto_incr_val contains | ||
| 12959 | // the next available value) into the atomic value. If the current | ||
| 12960 | // value no longer matches what we have in 'last_val' this will fail and | ||
| 12961 | // we will repeat the loop (`last_val` will automatically get updated | ||
| 12962 | // with the current value). | ||
| 12963 | // | ||
| 12964 | // See above explanation for inc == 1 for why we use std::min. | ||
| 12965 | 3056946 | } while (!auto_incr.compare_exchange_weak( | |
| 12966 |
2/2✓ Branch 0 taken 165526 times.
✓ Branch 1 taken 2986979 times.
|
6212480 | last_val, std::min(new_val + 1, max_val))); |
| 12967 | } | ||
| 12968 | } | ||
| 12969 | |||
| 12970 | 6745963 | *first_value = new_val; | |
| 12971 | 6745963 | *nb_reserved_values = 1; | |
| 12972 | 6745963 | } | |
| 12973 | |||
| 12974 | #ifndef NDEBUG | ||
| 12975 | |||
| 12976 | /* Debugger help function */ | ||
| 12977 | static char dbug_item_print_buf[512]; | ||
| 12978 | |||
| 12979 | ✗ | const char *dbug_print_item(const THD *thd, Item *const item) { | |
| 12980 | ✗ | char *const buf = dbug_item_print_buf; | |
| 12981 | ✗ | String str(buf, sizeof(dbug_item_print_buf), &my_charset_bin); | |
| 12982 | ✗ | str.length(0); | |
| 12983 | ✗ | if (!item) return "(Item*)nullptr"; | |
| 12984 | ✗ | item->print(thd, &str, QT_ORDINARY); | |
| 12985 | ✗ | if (str.c_ptr() == buf) { | |
| 12986 | ✗ | return buf; | |
| 12987 | } else { | ||
| 12988 | ✗ | return "Couldn't fit into buffer"; | |
| 12989 | } | ||
| 12990 | } | ||
| 12991 | |||
| 12992 | #endif /*NDEBUG*/ | ||
| 12993 | |||
| 12994 | /** | ||
| 12995 | SQL layer calls this function to push an index condition. | ||
| 12996 | |||
| 12997 | @details | ||
| 12998 | The condition is for index keyno (only one condition can be pushed at a | ||
| 12999 | time). | ||
| 13000 | The caller guarantees that condition refers only to index fields; besides | ||
| 13001 | that, fields must have | ||
| 13002 | |||
| 13003 | $field->part_of_key.set_bit(keyno) | ||
| 13004 | |||
| 13005 | which means that | ||
| 13006 | |||
| 13007 | (handler->index_flags(keyno, $keypart, 0) & HA_KEYREAD_ONLY) == 1 | ||
| 13008 | |||
| 13009 | which means that field value can be restored from the index tuple. | ||
| 13010 | |||
| 13011 | @return | ||
| 13012 | Part of condition we couldn't check (always nullptr). | ||
| 13013 | */ | ||
| 13014 | |||
| 13015 | 1675 | class Item *ha_rocksdb::idx_cond_push(uint keyno, class Item *const idx_cond) { | |
| 13016 |
1/2✓ Branch 0 taken 1675 times.
✗ Branch 1 not taken.
|
1675 | DBUG_ENTER_FUNC(); |
| 13017 | |||
| 13018 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1675 times.
|
1675 | assert(keyno != MAX_KEY); |
| 13019 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1675 times.
|
1675 | assert(idx_cond != nullptr); |
| 13020 | |||
| 13021 | 1675 | pushed_idx_cond = idx_cond; | |
| 13022 | 1675 | pushed_idx_cond_keyno = keyno; | |
| 13023 | 1675 | in_range_check_pushed_down = true; | |
| 13024 | |||
| 13025 | /* We will check the whole condition */ | ||
| 13026 |
1/2✓ Branch 0 taken 1675 times.
✗ Branch 1 not taken.
|
1675 | DBUG_RETURN(nullptr); |
| 13027 | } | ||
| 13028 | |||
| 13029 | /* | ||
| 13030 | @brief | ||
| 13031 | Check the index condition. | ||
| 13032 | |||
| 13033 | @detail | ||
| 13034 | Check the index condition. (The caller has unpacked all needed index | ||
| 13035 | columns into table->record[0]) | ||
| 13036 | |||
| 13037 | @return | ||
| 13038 | ICP_NO_MATCH - Condition not satisfied (caller should continue | ||
| 13039 | scanning) | ||
| 13040 | OUT_OF_RANGE - We've left the range we're scanning (caller should | ||
| 13041 | stop scanning and return HA_ERR_END_OF_FILE) | ||
| 13042 | |||
| 13043 | ICP_MATCH - Condition is satisfied (caller should fetch the record | ||
| 13044 | and return it) | ||
| 13045 | */ | ||
| 13046 | |||
| 13047 | 46503 | enum icp_result ha_rocksdb::check_index_cond() const { | |
| 13048 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46503 times.
|
46503 | assert(pushed_idx_cond); |
| 13049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46503 times.
|
46503 | assert(pushed_idx_cond_keyno != MAX_KEY); |
| 13050 | |||
| 13051 |
6/6✓ Branch 0 taken 19587 times.
✓ Branch 1 taken 26916 times.
✓ Branch 2 taken 365 times.
✓ Branch 3 taken 19222 times.
✓ Branch 4 taken 365 times.
✓ Branch 5 taken 46138 times.
|
46503 | if (end_range && compare_key_icp(end_range) > 0) { |
| 13052 | /* caller should return HA_ERR_END_OF_FILE already */ | ||
| 13053 | 365 | return ICP_OUT_OF_RANGE; | |
| 13054 | } | ||
| 13055 | |||
| 13056 |
2/2✓ Branch 0 taken 45919 times.
✓ Branch 1 taken 219 times.
|
46138 | return pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH; |
| 13057 | } | ||
| 13058 | |||
| 13059 | /** Operations for altering a table that RocksDB does not care about */ | ||
| 13060 | static const Alter_inplace_info::HA_ALTER_FLAGS ROCKSDB_INPLACE_IGNORE = | ||
| 13061 | Alter_inplace_info::ALTER_COLUMN_DEFAULT | | ||
| 13062 | Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT | | ||
| 13063 | Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE | | ||
| 13064 | Alter_inplace_info::ALTER_RENAME | Alter_inplace_info::CHANGE_INDEX_OPTION | | ||
| 13065 | Alter_inplace_info::ADD_CHECK_CONSTRAINT | | ||
| 13066 | Alter_inplace_info::DROP_CHECK_CONSTRAINT | | ||
| 13067 | Alter_inplace_info::SUSPEND_CHECK_CONSTRAINT; | ||
| 13068 | |||
| 13069 | /* | ||
| 13070 | Checks if instant alter is supported for a given operation. | ||
| 13071 | */ | ||
| 13072 | 2263 | ha_rocksdb::Instant_Type ha_rocksdb::rocksdb_support_instant( | |
| 13073 | my_core::Alter_inplace_info *const ha_alter_info MY_ATTRIBUTE((unused)), | ||
| 13074 | const TABLE *old_table MY_ATTRIBUTE((unused)), | ||
| 13075 | const TABLE *altered_table MY_ATTRIBUTE((unused))) const { | ||
| 13076 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2263 times.
|
2263 | if (rocksdb_instant_ddl) { |
| 13077 | ✗ | return Instant_Type::INSTANT_IMPOSSIBLE; | |
| 13078 | } | ||
| 13079 | |||
| 13080 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 2197 times.
|
2263 | if (!(ha_alter_info->handler_flags & ~ROCKSDB_INPLACE_IGNORE)) { |
| 13081 | /* after adding support, return (Instant_Type::INSTANT_NO_CHANGE) */ | ||
| 13082 | 66 | return (Instant_Type::INSTANT_IMPOSSIBLE); | |
| 13083 | } | ||
| 13084 | |||
| 13085 | 2197 | Alter_inplace_info::HA_ALTER_FLAGS alter_inplace_flags = | |
| 13086 | 2197 | ha_alter_info->handler_flags & ~ROCKSDB_INPLACE_IGNORE; | |
| 13087 | |||
| 13088 | /* If it's only adding and(or) dropping virtual columns */ | ||
| 13089 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2164 times.
|
2197 | if (!(alter_inplace_flags & ~(Alter_inplace_info::ADD_VIRTUAL_COLUMN | |
| 13090 | Alter_inplace_info::DROP_VIRTUAL_COLUMN))) { | ||
| 13091 | /* after enable, return (Instant_Type::INSTANT_VIRTUAL_ONLY); */ | ||
| 13092 | 33 | return (Instant_Type::INSTANT_IMPOSSIBLE); | |
| 13093 | } | ||
| 13094 | |||
| 13095 | /* If it's an ADD COLUMN without changing existing column orders */ | ||
| 13096 |
2/2✓ Branch 0 taken 127 times.
✓ Branch 1 taken 2037 times.
|
2164 | if (alter_inplace_flags == Alter_inplace_info::ADD_STORED_BASE_COLUMN) { |
| 13097 | /* after add col instant support, return Instant_Type::INSTANT_ADD_COLUMN | ||
| 13098 | * */ | ||
| 13099 | 127 | return (Instant_Type::INSTANT_IMPOSSIBLE); | |
| 13100 | } | ||
| 13101 | |||
| 13102 | // by default, impossible to do instant ddl | ||
| 13103 | 2037 | return (Instant_Type::INSTANT_IMPOSSIBLE); | |
| 13104 | } | ||
| 13105 | |||
| 13106 | /* | ||
| 13107 | Checks if inplace alter is supported for a given operation. | ||
| 13108 | */ | ||
| 13109 | 2269 | my_core::enum_alter_inplace_result ha_rocksdb::check_if_supported_inplace_alter( | |
| 13110 | TABLE *altered_table, my_core::Alter_inplace_info *ha_alter_info) { | ||
| 13111 |
1/2✓ Branch 0 taken 2269 times.
✗ Branch 1 not taken.
|
2269 | DBUG_ENTER_FUNC(); |
| 13112 | |||
| 13113 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2269 times.
|
2269 | assert(ha_alter_info != nullptr); |
| 13114 | |||
| 13115 | /* No need for a table rebuild when changing only index metadata */ | ||
| 13116 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2263 times.
|
2269 | if (ha_alter_info->handler_flags == Alter_inplace_info::RENAME_INDEX && |
| 13117 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ha_alter_info->alter_info->flags == Alter_info::ALTER_INDEX_VISIBILITY && |
| 13118 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ha_alter_info->create_info->used_fields == 0) { |
| 13119 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_RETURN(my_core::HA_ALTER_INPLACE_EXCLUSIVE_LOCK); |
| 13120 | } | ||
| 13121 | |||
| 13122 | /* check instant ddl type */ | ||
| 13123 | Instant_Type instant_type = | ||
| 13124 |
1/2✓ Branch 0 taken 2263 times.
✗ Branch 1 not taken.
|
2263 | rocksdb_support_instant(ha_alter_info, this->table, altered_table); |
| 13125 | |||
| 13126 | /* by default, impossible to do intant ddl */ | ||
| 13127 | 2263 | ha_alter_info->handler_trivial_ctx = | |
| 13128 | static_cast<uint8>(Instant_Type::INSTANT_IMPOSSIBLE); | ||
| 13129 | |||
| 13130 |
1/4✓ Branch 0 taken 2263 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2263 | switch (instant_type) { |
| 13131 | 2263 | case Instant_Type::INSTANT_IMPOSSIBLE: | |
| 13132 | 2263 | break; | |
| 13133 | ✗ | case Instant_Type::INSTANT_ADD_COLUMN: | |
| 13134 | ✗ | if (ha_alter_info->alter_info->requested_algorithm == | |
| 13135 | Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) { | ||
| 13136 | /* Still fall back to INPLACE since the behaviour is different */ | ||
| 13137 | ✗ | break; | |
| 13138 | ✗ | } else if (ha_alter_info->error_if_not_empty) { | |
| 13139 | /* In this case, it can't be instant because the table | ||
| 13140 | may not be empty. Have to fall back to INPLACE */ | ||
| 13141 | ✗ | break; | |
| 13142 | } | ||
| 13143 | [[fallthrough]]; | ||
| 13144 | case Instant_Type::INSTANT_NO_CHANGE: | ||
| 13145 | case Instant_Type::INSTANT_VIRTUAL_ONLY: | ||
| 13146 | ✗ | ha_alter_info->handler_trivial_ctx = static_cast<uint8>(instant_type); | |
| 13147 | ✗ | DBUG_RETURN(HA_ALTER_INPLACE_INSTANT); | |
| 13148 | } | ||
| 13149 | |||
| 13150 |
2/2✓ Branch 0 taken 1293 times.
✓ Branch 1 taken 970 times.
|
2263 | if (ha_alter_info->handler_flags & |
| 13151 |
2/2✓ Branch 0 taken 2254 times.
✓ Branch 1 taken 9 times.
|
2263 | ~(my_core::Alter_inplace_info::DROP_INDEX | |
| 13152 | my_core::Alter_inplace_info::DROP_UNIQUE_INDEX | | ||
| 13153 | my_core::Alter_inplace_info::ADD_INDEX | | ||
| 13154 | my_core::Alter_inplace_info::ADD_UNIQUE_INDEX | | ||
| 13155 | my_core::Alter_inplace_info::CHANGE_CREATE_OPTION | | ||
| 13156 | my_core::Alter_inplace_info::DROP_PARTITION | | ||
| 13157 | (rocksdb_alter_column_default_inplace | ||
| 13158 | ? my_core::Alter_inplace_info::ALTER_COLUMN_DEFAULT | ||
| 13159 | : 0))) { | ||
| 13160 |
1/2✓ Branch 0 taken 1293 times.
✗ Branch 1 not taken.
|
1293 | DBUG_RETURN(my_core::HA_ALTER_INPLACE_NOT_SUPPORTED); |
| 13161 | } | ||
| 13162 | |||
| 13163 | /* We don't support unique keys on table w/ no primary keys */ | ||
| 13164 | 1940 | if ((ha_alter_info->handler_flags & | |
| 13165 |
4/4✓ Branch 0 taken 51 times.
✓ Branch 1 taken 919 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 955 times.
|
1021 | my_core::Alter_inplace_info::ADD_UNIQUE_INDEX) && |
| 13166 |
3/4✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 36 times.
|
51 | has_hidden_pk(altered_table)) { |
| 13167 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | DBUG_RETURN(my_core::HA_ALTER_INPLACE_NOT_SUPPORTED); |
| 13168 | } | ||
| 13169 | |||
| 13170 | /* We only support changing auto_increment for table options. */ | ||
| 13171 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 769 times.
|
955 | if ((ha_alter_info->handler_flags & |
| 13172 | 186 | my_core::Alter_inplace_info::CHANGE_CREATE_OPTION) && | |
| 13173 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 90 times.
|
186 | !(ha_alter_info->create_info->used_fields & HA_CREATE_USED_AUTO)) { |
| 13174 |
1/2✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
|
96 | DBUG_RETURN(my_core::HA_ALTER_INPLACE_NOT_SUPPORTED); |
| 13175 | } | ||
| 13176 | |||
| 13177 |
1/2✓ Branch 0 taken 859 times.
✗ Branch 1 not taken.
|
859 | DBUG_RETURN(my_core::HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE); |
| 13178 | } | ||
| 13179 | |||
| 13180 | /** | ||
| 13181 | Allows the storage engine to update internal structures with concurrent | ||
| 13182 | writes blocked. If check_if_supported_inplace_alter() returns | ||
| 13183 | HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE or | ||
| 13184 | HA_ALTER_INPLACE_SHARED_AFTER_PREPARE, this function is called with | ||
| 13185 | exclusive lock otherwise the same level of locking as for | ||
| 13186 | inplace_alter_table() will be used. | ||
| 13187 | |||
| 13188 | @note Storage engines are responsible for reporting any errors by | ||
| 13189 | calling my_error()/print_error() | ||
| 13190 | |||
| 13191 | @note If this function reports error, commit_inplace_alter_table() | ||
| 13192 | will be called with commit= false. | ||
| 13193 | |||
| 13194 | @note For partitioning, failing to prepare one partition, means that | ||
| 13195 | commit_inplace_alter_table() will be called to roll back changes for | ||
| 13196 | all partitions. This means that commit_inplace_alter_table() might be | ||
| 13197 | called without prepare_inplace_alter_table() having been called first | ||
| 13198 | for a given partition. | ||
| 13199 | |||
| 13200 | @param altered_table TABLE object for new version of table. | ||
| 13201 | @param ha_alter_info Structure describing changes to be done | ||
| 13202 | by ALTER TABLE and holding data used | ||
| 13203 | during in-place alter. | ||
| 13204 | |||
| 13205 | @retval true Error | ||
| 13206 | @retval false Success | ||
| 13207 | */ | ||
| 13208 | 1144 | bool ha_rocksdb::prepare_inplace_alter_table( | |
| 13209 | TABLE *altered_table, my_core::Alter_inplace_info *ha_alter_info, | ||
| 13210 | const dd::Table *old_table_def MY_ATTRIBUTE((__unused__)), | ||
| 13211 | dd::Table *new_table_def MY_ATTRIBUTE((__unused__))) { | ||
| 13212 |
1/2✓ Branch 0 taken 1144 times.
✗ Branch 1 not taken.
|
1144 | DBUG_ENTER_FUNC(); |
| 13213 | |||
| 13214 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1144 times.
|
1144 | assert(altered_table != nullptr); |
| 13215 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1144 times.
|
1144 | assert(ha_alter_info != nullptr); |
| 13216 | |||
| 13217 | 1144 | Rdb_tbl_def *new_tdef = nullptr; | |
| 13218 | 1144 | std::shared_ptr<Rdb_key_def> *old_key_descr = nullptr; | |
| 13219 | 1144 | std::shared_ptr<Rdb_key_def> *new_key_descr = nullptr; | |
| 13220 | 1144 | uint old_n_keys = m_tbl_def->m_key_count; | |
| 13221 | 1144 | uint new_n_keys = altered_table->s->keys; | |
| 13222 | 1144 | std::unordered_set<std::shared_ptr<Rdb_key_def>> added_indexes; | |
| 13223 | 1144 | std::unordered_set<GL_INDEX_ID> dropped_index_ids; | |
| 13224 | 1144 | uint n_dropped_keys = 0; | |
| 13225 | 1144 | uint n_added_keys = 0; | |
| 13226 | 1144 | ulonglong max_auto_incr = 0; | |
| 13227 | |||
| 13228 |
2/2✓ Branch 0 taken 601 times.
✓ Branch 1 taken 543 times.
|
1144 | if (ha_alter_info->handler_flags & |
| 13229 | (my_core::Alter_inplace_info::DROP_INDEX | | ||
| 13230 | my_core::Alter_inplace_info::DROP_UNIQUE_INDEX | | ||
| 13231 | my_core::Alter_inplace_info::ADD_INDEX | | ||
| 13232 | my_core::Alter_inplace_info::ADD_UNIQUE_INDEX)) { | ||
| 13233 |
3/4✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 409 times.
|
601 | if (has_hidden_pk(altered_table)) { |
| 13234 | 192 | new_n_keys += 1; | |
| 13235 | } | ||
| 13236 | |||
| 13237 | 601 | const TABLE *const old_table = table; | |
| 13238 | 601 | old_key_descr = m_tbl_def->m_key_descr_arr; | |
| 13239 |
4/6✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1435 times.
✓ Branch 5 taken 601 times.
|
2036 | new_key_descr = new std::shared_ptr<Rdb_key_def>[new_n_keys]; |
| 13240 | |||
| 13241 |
2/4✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
|
601 | new_tdef = new Rdb_tbl_def(m_tbl_def->full_tablename()); |
| 13242 | 601 | new_tdef->m_key_descr_arr = new_key_descr; | |
| 13243 | 601 | new_tdef->m_key_count = new_n_keys; | |
| 13244 | 601 | new_tdef->m_pk_index = altered_table->s->primary_key; | |
| 13245 | 601 | new_tdef->m_auto_incr_val = | |
| 13246 | 601 | m_tbl_def->m_auto_incr_val.load(std::memory_order_relaxed); | |
| 13247 | 601 | new_tdef->m_hidden_pk_val = | |
| 13248 | 601 | m_tbl_def->m_hidden_pk_val.load(std::memory_order_relaxed); | |
| 13249 | |||
| 13250 |
4/6✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 601 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 589 times.
|
601 | if (create_key_defs(altered_table, new_tdef, "" /*actual_user_table_name*/, |
| 13251 | 601 | table, m_tbl_def)) { | |
| 13252 | /* Delete the new key descriptors */ | ||
| 13253 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
48 | delete[] new_key_descr; |
| 13254 | |||
| 13255 | /* | ||
| 13256 | Explicitly mark as nullptr so we don't accidentally remove entries | ||
| 13257 | from data dictionary on cleanup (or cause double delete[]). | ||
| 13258 | */ | ||
| 13259 | 12 | new_tdef->m_key_descr_arr = nullptr; | |
| 13260 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | delete new_tdef; |
| 13261 | |||
| 13262 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | my_error(ER_KEY_CREATE_DURING_ALTER, MYF(0)); |
| 13263 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 13264 | } | ||
| 13265 | |||
| 13266 | uint i; | ||
| 13267 | uint j; | ||
| 13268 | |||
| 13269 | /* Determine which(if any) key definition(s) need to be dropped */ | ||
| 13270 |
2/2✓ Branch 0 taken 182 times.
✓ Branch 1 taken 589 times.
|
771 | for (i = 0; i < ha_alter_info->index_drop_count; i++) { |
| 13271 | 182 | const KEY *const dropped_key = ha_alter_info->index_drop_buffer[i]; | |
| 13272 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | for (j = 0; j < old_n_keys; j++) { |
| 13273 | const KEY *const old_key = | ||
| 13274 | 358 | &old_table->key_info[old_key_descr[j]->get_keyno()]; | |
| 13275 | |||
| 13276 |
3/4✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✓ Branch 3 taken 176 times.
|
358 | if (!compare_keys(old_key, dropped_key)) { |
| 13277 |
2/4✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✗ Branch 3 not taken.
|
182 | dropped_index_ids.insert(old_key_descr[j]->get_gl_index_id()); |
| 13278 | 182 | break; | |
| 13279 | } | ||
| 13280 | } | ||
| 13281 | } | ||
| 13282 | |||
| 13283 | /* Determine which(if any) key definitions(s) need to be added */ | ||
| 13284 | 589 | int identical_indexes_found = 0; | |
| 13285 |
2/2✓ Branch 0 taken 466 times.
✓ Branch 1 taken 589 times.
|
1055 | for (i = 0; i < ha_alter_info->index_add_count; i++) { |
| 13286 | 466 | const KEY *const added_key = | |
| 13287 | 466 | &ha_alter_info->key_info_buffer[ha_alter_info->index_add_buffer[i]]; | |
| 13288 |
1/2✓ Branch 0 taken 1013 times.
✗ Branch 1 not taken.
|
1013 | for (j = 0; j < new_n_keys; j++) { |
| 13289 | const KEY *const new_key = | ||
| 13290 | 1013 | &altered_table->key_info[new_key_descr[j]->get_keyno()]; | |
| 13291 |
3/4✓ Branch 0 taken 1013 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 466 times.
✓ Branch 3 taken 547 times.
|
1013 | if (!compare_keys(new_key, added_key)) { |
| 13292 | /* | ||
| 13293 | Check for cases where an 'identical' index is being dropped and | ||
| 13294 | re-added in a single ALTER statement. Turn this into a no-op as the | ||
| 13295 | index has not changed. | ||
| 13296 | |||
| 13297 | E.G. Unique index -> non-unique index requires no change | ||
| 13298 | |||
| 13299 | Note that cases where the index name remains the same but the | ||
| 13300 | key-parts are changed is already handled in create_inplace_key_defs. | ||
| 13301 | In these cases the index needs to be rebuilt. | ||
| 13302 | */ | ||
| 13303 |
3/6✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 466 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 466 times.
|
466 | if (dropped_index_ids.count(new_key_descr[j]->get_gl_index_id())) { |
| 13304 | ✗ | dropped_index_ids.erase(new_key_descr[j]->get_gl_index_id()); | |
| 13305 | ✗ | identical_indexes_found++; | |
| 13306 | } else { | ||
| 13307 |
1/2✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
|
466 | added_indexes.insert(new_key_descr[j]); |
| 13308 | } | ||
| 13309 | |||
| 13310 | 466 | break; | |
| 13311 | } | ||
| 13312 | } | ||
| 13313 | } | ||
| 13314 | |||
| 13315 | 589 | n_dropped_keys = ha_alter_info->index_drop_count - identical_indexes_found; | |
| 13316 | 589 | n_added_keys = ha_alter_info->index_add_count - identical_indexes_found; | |
| 13317 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
|
589 | assert(dropped_index_ids.size() == n_dropped_keys); |
| 13318 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
|
589 | assert(added_indexes.size() == n_added_keys); |
| 13319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
|
589 | assert(new_n_keys == (old_n_keys - n_dropped_keys + n_added_keys)); |
| 13320 | } | ||
| 13321 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 1042 times.
|
1132 | if (ha_alter_info->handler_flags & |
| 13322 | my_core::Alter_inplace_info::CHANGE_CREATE_OPTION) { | ||
| 13323 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 24 times.
|
90 | if (!new_tdef) { |
| 13324 | 66 | new_tdef = m_tbl_def; | |
| 13325 | } | ||
| 13326 |
2/2✓ Branch 0 taken 87 times.
✓ Branch 1 taken 3 times.
|
90 | if (table->found_next_number_field) { |
| 13327 |
1/2✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
|
87 | max_auto_incr = load_auto_incr_value_from_index(); |
| 13328 | } | ||
| 13329 | } | ||
| 13330 | |||
| 13331 |
4/8✓ Branch 0 taken 1132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1132 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1132 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1132 times.
✗ Branch 7 not taken.
|
3396 | ha_alter_info->handler_ctx = new (*THR_MALLOC) |
| 13332 | Rdb_inplace_alter_ctx(new_tdef, old_key_descr, new_key_descr, old_n_keys, | ||
| 13333 | new_n_keys, added_indexes, dropped_index_ids, | ||
| 13334 |
1/2✓ Branch 0 taken 1132 times.
✗ Branch 1 not taken.
|
2264 | n_added_keys, n_dropped_keys, max_auto_incr); |
| 13335 |
1/2✓ Branch 0 taken 1132 times.
✗ Branch 1 not taken.
|
1132 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 13336 | 1144 | } | |
| 13337 | |||
| 13338 | /** | ||
| 13339 | Alter the table structure in-place with operations specified using | ||
| 13340 | HA_ALTER_FLAGS and Alter_inplace_info. The level of concurrency allowed | ||
| 13341 | during this operation depends on the return value from | ||
| 13342 | check_if_supported_inplace_alter(). | ||
| 13343 | |||
| 13344 | @note Storage engines are responsible for reporting any errors by | ||
| 13345 | calling my_error()/print_error() | ||
| 13346 | |||
| 13347 | @note If this function reports error, commit_inplace_alter_table() | ||
| 13348 | will be called with commit= false. | ||
| 13349 | |||
| 13350 | @param altered_table TABLE object for new version of table. | ||
| 13351 | @param ha_alter_info Structure describing changes to be done | ||
| 13352 | by ALTER TABLE and holding data used | ||
| 13353 | during in-place alter. | ||
| 13354 | |||
| 13355 | @retval true Error | ||
| 13356 | @retval false Success | ||
| 13357 | */ | ||
| 13358 | 1129 | bool ha_rocksdb::inplace_alter_table( | |
| 13359 | TABLE *altered_table, my_core::Alter_inplace_info *ha_alter_info, | ||
| 13360 | const dd::Table *old_table_def MY_ATTRIBUTE((__unused__)), | ||
| 13361 | dd::Table *new_table_def MY_ATTRIBUTE((__unused__))) { | ||
| 13362 |
1/2✓ Branch 0 taken 1129 times.
✗ Branch 1 not taken.
|
1129 | DBUG_ENTER_FUNC(); |
| 13363 | |||
| 13364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1129 times.
|
1129 | assert(altered_table != nullptr); |
| 13365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1129 times.
|
1129 | assert(ha_alter_info != nullptr); |
| 13366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1129 times.
|
1129 | assert(ha_alter_info->handler_ctx != nullptr); |
| 13367 | |||
| 13368 | 1129 | bool res = HA_EXIT_SUCCESS; | |
| 13369 | 1129 | Rdb_inplace_alter_ctx *const ctx = | |
| 13370 | static_cast<Rdb_inplace_alter_ctx *>(ha_alter_info->handler_ctx); | ||
| 13371 | |||
| 13372 |
2/2✓ Branch 0 taken 686 times.
✓ Branch 1 taken 443 times.
|
1129 | if (!(ha_alter_info->handler_flags & |
| 13373 | (my_core::Alter_inplace_info::ADD_INDEX | | ||
| 13374 | my_core::Alter_inplace_info::ADD_UNIQUE_INDEX))) { | ||
| 13375 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | DBUG_RETURN(res); |
| 13376 | } | ||
| 13377 | |||
| 13378 | /* | ||
| 13379 | Buffers need to be set up again to account for new, possibly longer | ||
| 13380 | secondary keys. | ||
| 13381 | */ | ||
| 13382 |
1/2✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
|
443 | free_key_buffers(); |
| 13383 | |||
| 13384 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
|
443 | assert(ctx != nullptr); |
| 13385 | |||
| 13386 | /* | ||
| 13387 | If adding unique index, allocate special buffers for duplicate checking. | ||
| 13388 | */ | ||
| 13389 | int err; | ||
| 13390 |
2/4✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 443 times.
|
443 | if ((err = alloc_key_buffers(altered_table, ctx->m_new_tdef))) { |
| 13391 | ✗ | my_error(ER_OUT_OF_RESOURCES, MYF(0)); | |
| 13392 | ✗ | res = HA_EXIT_FAILURE; | |
| 13393 | ✗ | goto end; | |
| 13394 | } | ||
| 13395 | |||
| 13396 | /* Populate all new secondary keys by scanning the primary key. */ | ||
| 13397 |
3/4✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 416 times.
|
443 | if ((err = inplace_populate_sk(altered_table, ctx->m_added_indexes))) { |
| 13398 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | my_error(ER_SK_POPULATE_DURING_ALTER, MYF(0)); |
| 13399 | 24 | res = HA_EXIT_FAILURE; | |
| 13400 | 24 | goto end; | |
| 13401 | } | ||
| 13402 | |||
| 13403 |
4/6✓ Branch 0 taken 416 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 415 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
416 | DBUG_EXECUTE_IF("myrocks_simulate_index_create_rollback", { |
| 13404 | dbug_create_err_inplace_alter(); | ||
| 13405 | res = HA_EXIT_FAILURE; | ||
| 13406 | };); | ||
| 13407 | |||
| 13408 | 415 | end: | |
| 13409 | // During inplace_populate_sk, we may perform duplicate key checking which | ||
| 13410 | // involves calling unpack_record. However, blobs end up being unpacked | ||
| 13411 | // using the buffer in altered_table->file, instead of the current handler | ||
| 13412 | // object. This handler does not get cleaned up as it was never | ||
| 13413 | // opened, so we end up leaking that buffer. To fix, we call free_key_buffers | ||
| 13414 | // here. | ||
| 13415 | // | ||
| 13416 | // In the partitioned case, the altered_table->file is not only unopened, but | ||
| 13417 | // also unintialized, but we only unpack on duplicate key errors, and the | ||
| 13418 | // error is not possible on partitioned tables because indexes must include | ||
| 13419 | // the partitioning key which must include the primary key. | ||
| 13420 | // | ||
| 13421 | // A better solution would be to pass in the blob buffer from the correct | ||
| 13422 | // handler explicitly into the unpack functions, so that | ||
| 13423 | // Rdb_key_def::unpack_record does not need to derive it from the TABLE | ||
| 13424 | // object, since the Rdb_key_def class are generally unaware of handler | ||
| 13425 | // classes anyway. | ||
| 13426 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 425 times.
|
440 | if (err == ER_DUP_ENTRY) { |
| 13427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(ha_alter_info->group_commit_ctx == nullptr); |
| 13428 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | reinterpret_cast<ha_rocksdb *>(altered_table->file)->free_key_buffers(); |
| 13429 | } | ||
| 13430 | |||
| 13431 | // Try to reallocate key buffers from the old schema. | ||
| 13432 | // | ||
| 13433 | // A better fix may to save the original buffers to avoid needing to | ||
| 13434 | // reallocate here. | ||
| 13435 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 415 times.
|
440 | if (res == HA_EXIT_FAILURE) { |
| 13436 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | free_key_buffers(); |
| 13437 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | err = alloc_key_buffers(table, m_tbl_def); |
| 13438 | } | ||
| 13439 | |||
| 13440 |
1/2✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
|
440 | DBUG_RETURN(res); |
| 13441 | } | ||
| 13442 | |||
| 13443 | 20898676 | int ha_rocksdb::fill_virtual_columns() { | |
| 13444 | /* Specify the columns the server should evaluate */ | ||
| 13445 | 20898676 | MY_BITMAP column_map; | |
| 13446 | 20898676 | bool bitmap_inited = false; | |
| 13447 | my_bitmap_map col_map_storage[bitmap_buffer_size(1023)]; | ||
| 13448 |
2/2✓ Branch 0 taken 59583251 times.
✓ Branch 1 taken 20898676 times.
|
80481927 | for (uint i = 0; i < table->s->fields; i++) { |
| 13449 | 59583251 | auto &field = table->field[i]; | |
| 13450 |
2/2✓ Branch 0 taken 40410 times.
✓ Branch 1 taken 59542841 times.
|
59583251 | if (field->is_virtual_gcol()) { |
| 13451 |
2/2✓ Branch 0 taken 19560 times.
✓ Branch 1 taken 20850 times.
|
40410 | if (!bitmap_inited) { |
| 13452 |
1/2✓ Branch 0 taken 19560 times.
✗ Branch 1 not taken.
|
19560 | bitmap_init(&column_map, col_map_storage, 1023); |
| 13453 | 19560 | bitmap_inited = true; | |
| 13454 | } | ||
| 13455 | 40410 | bitmap_set_bit(&column_map, i); | |
| 13456 | } | ||
| 13457 | } | ||
| 13458 |
2/2✓ Branch 0 taken 19560 times.
✓ Branch 1 taken 20879116 times.
|
20898676 | if (bitmap_inited) { |
| 13459 |
1/2✓ Branch 0 taken 19560 times.
✗ Branch 1 not taken.
|
19560 | THD *const thd = my_core::thd_get_current_thd(); |
| 13460 | 39120 | int ret = handler::my_eval_gcolumn_expr( | |
| 13461 | thd, const_cast<TABLE *>(table), &column_map, | ||
| 13462 |
1/2✓ Branch 0 taken 19560 times.
✗ Branch 1 not taken.
|
19560 | const_cast<uchar *>(table->record[0]), nullptr, nullptr); |
| 13463 | |||
| 13464 | 19560 | return ret; | |
| 13465 | } | ||
| 13466 | 20879116 | return 0; | |
| 13467 | } | ||
| 13468 | |||
| 13469 | /** | ||
| 13470 | Scan the Primary Key index entries and populate the new secondary keys. | ||
| 13471 | */ | ||
| 13472 | 443 | int ha_rocksdb::inplace_populate_sk( | |
| 13473 | TABLE *const new_table_arg, | ||
| 13474 | const std::unordered_set<std::shared_ptr<Rdb_key_def>> &indexes) { | ||
| 13475 |
1/2✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
|
443 | DBUG_ENTER_FUNC(); |
| 13476 | 443 | int res = HA_EXIT_SUCCESS; | |
| 13477 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
|
443 | assert(indexes.size() > 0); |
| 13478 |
1/2✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
|
443 | uint table_default_cf_id = (*indexes.begin())->get_cf()->GetID(); |
| 13479 | auto local_dict_manager = | ||
| 13480 |
1/2✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
|
443 | dict_manager.get_dict_manager_selector_non_const(table_default_cf_id); |
| 13481 |
1/2✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
|
443 | const std::unique_ptr<rocksdb::WriteBatch> wb = local_dict_manager->begin(); |
| 13482 | 443 | rocksdb::WriteBatch *const batch = wb.get(); | |
| 13483 | |||
| 13484 |
6/10✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 440 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
443 | DBUG_EXECUTE_IF("rocksdb_inplace_populate_sk", { |
| 13485 | static constexpr char act[] = | ||
| 13486 | "now signal ready_to_mark_cf_dropped_in_populate_sk " | ||
| 13487 | "wait_for mark_cf_dropped_done_in_populate_sk"; | ||
| 13488 | assert(!debug_sync_set_action(ha_thd(), STRING_WITH_LEN(act))); | ||
| 13489 | }); | ||
| 13490 | |||
| 13491 | { | ||
| 13492 |
1/2✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
|
443 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 13493 |
2/2✓ Branch 0 taken 463 times.
✓ Branch 1 taken 440 times.
|
903 | for (const auto &kd : indexes) { |
| 13494 |
2/4✓ Branch 0 taken 463 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 463 times.
✗ Branch 3 not taken.
|
463 | const std::string cf_name = kd->get_cf()->GetName(); |
| 13495 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 13496 |
1/2✓ Branch 0 taken 463 times.
✗ Branch 1 not taken.
|
463 | cf_manager.get_cf(cf_name); |
| 13497 | |||
| 13498 |
4/8✓ Branch 0 taken 463 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 463 times.
✓ Branch 4 taken 463 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 463 times.
|
463 | if (!cfh || cfh != kd->get_shared_cf()) { |
| 13499 | // The CF has been dropped, i.e., cf_manager.remove_dropped_cf() has | ||
| 13500 | // been called. | ||
| 13501 | ✗ | DBUG_RETURN(HA_EXIT_FAILURE); | |
| 13502 | } | ||
| 13503 | |||
| 13504 |
1/2✓ Branch 0 taken 463 times.
✗ Branch 1 not taken.
|
463 | uint32 cf_id = cfh->GetID(); |
| 13505 |
3/4✓ Branch 0 taken 463 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 460 times.
|
463 | if (local_dict_manager->get_dropped_cf(cf_id)) { |
| 13506 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(HA_EXIT_FAILURE); |
| 13507 | } | ||
| 13508 |
4/4✓ Branch 0 taken 460 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 460 times.
✓ Branch 3 taken 3 times.
|
466 | } |
| 13509 | |||
| 13510 | /* Update the data dictionary */ | ||
| 13511 | 440 | std::unordered_set<GL_INDEX_ID> create_index_ids; | |
| 13512 |
2/2✓ Branch 0 taken 460 times.
✓ Branch 1 taken 440 times.
|
900 | for (const auto &index : indexes) { |
| 13513 |
2/4✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 460 times.
✗ Branch 3 not taken.
|
460 | create_index_ids.insert(index->get_gl_index_id()); |
| 13514 | } | ||
| 13515 |
1/2✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
|
440 | local_dict_manager->add_create_index(create_index_ids, batch); |
| 13516 |
1/2✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
|
440 | res = local_dict_manager->commit(batch); |
| 13517 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 440 times.
|
440 | if (res != HA_EXIT_SUCCESS) { |
| 13518 | ✗ | return res; | |
| 13519 | } | ||
| 13520 | |||
| 13521 | /* | ||
| 13522 | Add uncommitted key definitons to ddl_manager. We need to do this | ||
| 13523 | so that the property collector can find this keydef when it needs to | ||
| 13524 | update stats. The property collector looks for the keydef in the | ||
| 13525 | data dictionary, but it won't be there yet since this key definition | ||
| 13526 | is still in the creation process. | ||
| 13527 | */ | ||
| 13528 |
1/2✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
|
440 | ddl_manager.add_uncommitted_keydefs(indexes); |
| 13529 |
3/4✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 440 times.
✓ Branch 3 taken 3 times.
|
443 | } |
| 13530 | |||
| 13531 |
1/2✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
|
440 | const bool hidden_pk_exists = has_hidden_pk(table); |
| 13532 | |||
| 13533 |
1/2✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
|
440 | Rdb_transaction *tx = get_or_create_tx(table->in_use); |
| 13534 | |||
| 13535 | /* | ||
| 13536 | There is one specific scenario where m_sst_info may not be nullptr. This | ||
| 13537 | happens if the handler we're using happens to be the handler where the PK | ||
| 13538 | bulk load was done on. The sequence of events that lead to this is as | ||
| 13539 | follows (T1 is PK bulk load, T2 is SK alter table): | ||
| 13540 | |||
| 13541 | T1: Execute last INSERT statement | ||
| 13542 | T1: Return TABLE and handler object back to Table_cache_manager | ||
| 13543 | T1: Close connection | ||
| 13544 | T2: Execute ALTER statement | ||
| 13545 | T2: Take same TABLE/handler from Table_cache_manager | ||
| 13546 | T2: Call closefrm which will call finalize_bulk_load on every other open | ||
| 13547 | table/handler *except* the one it's on. | ||
| 13548 | T2: Acquire stale snapshot of PK | ||
| 13549 | T1: Call finalize_bulk_load | ||
| 13550 | |||
| 13551 | This is rare because usually, closefrm will call the destructor (and thus | ||
| 13552 | finalize_bulk_load) on the handler where PK bulk load is done. However, if | ||
| 13553 | the thread ids of the bulk load thread and the alter thread differ by a | ||
| 13554 | multiple of table_cache_instances (8 by default), then they hash to the | ||
| 13555 | same bucket in Table_cache_manager and the alter thread will not not call | ||
| 13556 | the destructor on the handler it is holding. Thus, its m_sst_info will not | ||
| 13557 | be nullptr. | ||
| 13558 | |||
| 13559 | At this point, it is safe to refresh the snapshot because we know all other | ||
| 13560 | open handlers have been closed at this point, and the one we're on is the | ||
| 13561 | only one left. | ||
| 13562 | */ | ||
| 13563 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 439 times.
|
440 | if (m_sst_info) { |
| 13564 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if ((res = finalize_bulk_load())) { |
| 13565 | ✗ | DBUG_RETURN(res); | |
| 13566 | } | ||
| 13567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | assert(tx->get_write_count() == 0); |
| 13568 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | tx->release_snapshot(); |
| 13569 | } | ||
| 13570 | |||
| 13571 |
2/2✓ Branch 0 taken 460 times.
✓ Branch 1 taken 437 times.
|
897 | for (const auto &index : indexes) { |
| 13572 | // Skip populating partial indexes. | ||
| 13573 |
6/10✓ Branch 0 taken 21 times.
✓ Branch 1 taken 439 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 21 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 460 times.
|
460 | if (index->is_partial_index() && !THDVAR(ha_thd(), bulk_load_partial_index)) |
| 13574 | ✗ | continue; | |
| 13575 | |||
| 13576 | /* | ||
| 13577 | Note: We use the currently existing table + tbl_def object here, | ||
| 13578 | as the pk index position may have changed in the case of hidden primary | ||
| 13579 | keys. | ||
| 13580 | */ | ||
| 13581 |
1/2✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
|
460 | res = ha_rnd_init(true /* scan */); |
| 13582 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
463 | if (res) DBUG_RETURN(res); |
| 13583 | |||
| 13584 | /* Scan each record in the primary key in order */ | ||
| 13585 |
3/4✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4579203 times.
✓ Branch 3 taken 457 times.
|
4579660 | for (res = ha_rnd_next(table->record[0]); res == 0; |
| 13586 |
1/2✓ Branch 0 taken 4579200 times.
✗ Branch 1 not taken.
|
4579200 | res = ha_rnd_next(table->record[0])) { |
| 13587 | 4579203 | longlong hidden_pk_id = 0; | |
| 13588 |
3/4✓ Branch 0 taken 15597 times.
✓ Branch 1 taken 4563606 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4579203 times.
|
4594800 | if (hidden_pk_exists && |
| 13589 |
2/4✓ Branch 0 taken 15597 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15597 times.
|
15597 | (res = read_hidden_pk_id_from_rowkey(&hidden_pk_id))) { |
| 13590 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Error retrieving hidden pk id."); | |
| 13591 | ✗ | ha_rnd_end(); | |
| 13592 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(res); |
| 13593 | } | ||
| 13594 | |||
| 13595 |
2/4✓ Branch 0 taken 4579203 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4579203 times.
|
4579203 | if ((res = fill_virtual_columns())) { |
| 13596 | ✗ | ha_rnd_end(); | |
| 13597 | ✗ | DBUG_RETURN(res); | |
| 13598 | } | ||
| 13599 | |||
| 13600 | /* Create new secondary index entry */ | ||
| 13601 | 4579203 | const int new_packed_size = index->pack_record( | |
| 13602 |
1/2✓ Branch 0 taken 4579203 times.
✗ Branch 1 not taken.
|
4579203 | new_table_arg, m_pack_buffer, table->record[0], m_sk_packed_tuple, |
| 13603 | 4579203 | &m_sk_tails, should_store_row_debug_checksums(), hidden_pk_id, 0, | |
| 13604 | 4579203 | nullptr, m_ttl_bytes); | |
| 13605 | |||
| 13606 | const rocksdb::Slice key = rocksdb::Slice( | ||
| 13607 | 4579203 | reinterpret_cast<const char *>(m_sk_packed_tuple), new_packed_size); | |
| 13608 | const rocksdb::Slice val = | ||
| 13609 | 4579203 | rocksdb::Slice(reinterpret_cast<const char *>(m_sk_tails.ptr()), | |
| 13610 | 9158406 | m_sk_tails.get_current_pos()); | |
| 13611 | |||
| 13612 | /* | ||
| 13613 | Add record to offset tree in preparation for writing out to | ||
| 13614 | disk in sorted chunks. | ||
| 13615 | */ | ||
| 13616 |
3/4✓ Branch 0 taken 4579203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4579200 times.
|
4579203 | if ((res = bulk_load_key(tx, *index, key, val, true))) { |
| 13617 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | ha_rnd_end(); |
| 13618 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_RETURN(res); |
| 13619 | } | ||
| 13620 | } | ||
| 13621 | |||
| 13622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
|
457 | if (res != HA_ERR_END_OF_FILE) { |
| 13623 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 13624 | "Error retrieving index entry from primary key."); | ||
| 13625 | ✗ | ha_rnd_end(); | |
| 13626 | ✗ | DBUG_RETURN(res); | |
| 13627 | } | ||
| 13628 | |||
| 13629 |
1/2✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
|
457 | ha_rnd_end(); |
| 13630 | |||
| 13631 | bool is_critical_error; | ||
| 13632 | 914 | res = tx->finish_bulk_load(&is_critical_error, true, new_table_arg, | |
| 13633 |
1/2✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
|
457 | m_table_handler->m_table_name); |
| 13634 | |||
| 13635 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 442 times.
|
457 | if (res == ER_DUP_ENTRY) { |
| 13636 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(new_table_arg->key_info[index->get_keyno()].flags & HA_NOSAME); |
| 13637 | 15 | print_keydup_error(new_table_arg, | |
| 13638 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | &new_table_arg->key_info[index->get_keyno()], MYF(0)); |
| 13639 | } | ||
| 13640 | |||
| 13641 |
3/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 439 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
457 | if (res && is_critical_error) { |
| 13642 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "Error finishing bulk load."); | |
| 13643 | ✗ | DBUG_RETURN(res); | |
| 13644 | } | ||
| 13645 | } | ||
| 13646 | |||
| 13647 | /* | ||
| 13648 | Explicitly tell jemalloc to clean up any unused dirty pages at this point. | ||
| 13649 | See https://reviews.facebook.net/D63723 for more details. | ||
| 13650 | */ | ||
| 13651 | 437 | purge_all_jemalloc_arenas(); | |
| 13652 | |||
| 13653 |
4/6✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 434 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
437 | DBUG_EXECUTE_IF("crash_during_online_index_creation", DBUG_SUICIDE();); |
| 13654 |
1/2✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
|
434 | DBUG_RETURN(res); |
| 13655 | 440 | } | |
| 13656 | |||
| 13657 | /** | ||
| 13658 | Commit or rollback the changes made during prepare_inplace_alter_table() | ||
| 13659 | and inplace_alter_table() inside the storage engine. | ||
| 13660 | Note that in case of rollback the allowed level of concurrency during | ||
| 13661 | this operation will be the same as for inplace_alter_table() and thus | ||
| 13662 | might be higher than during prepare_inplace_alter_table(). (For example, | ||
| 13663 | concurrent writes were blocked during prepare, but might not be during | ||
| 13664 | rollback). | ||
| 13665 | |||
| 13666 | @note Storage engines are responsible for reporting any errors by | ||
| 13667 | calling my_error()/print_error() | ||
| 13668 | |||
| 13669 | @note If this function with commit= true reports error, it will be called | ||
| 13670 | again with commit= false. | ||
| 13671 | |||
| 13672 | @note In case of partitioning, this function might be called for rollback | ||
| 13673 | without prepare_inplace_alter_table() having been called first. | ||
| 13674 | Also partitioned tables sets ha_alter_info->group_commit_ctx to a NULL | ||
| 13675 | terminated array of the partitions handlers and if all of them are | ||
| 13676 | committed as one, then group_commit_ctx should be set to NULL to indicate | ||
| 13677 | to the partitioning handler that all partitions handlers are committed. | ||
| 13678 | @see prepare_inplace_alter_table(). | ||
| 13679 | |||
| 13680 | @param altered_table TABLE object for new version of table. | ||
| 13681 | @param ha_alter_info Structure describing changes to be done | ||
| 13682 | by ALTER TABLE and holding data used | ||
| 13683 | during in-place alter. | ||
| 13684 | @param commit True => Commit, False => Rollback. | ||
| 13685 | |||
| 13686 | @retval true Error | ||
| 13687 | @retval false Success | ||
| 13688 | */ | ||
| 13689 | 844 | bool ha_rocksdb::commit_inplace_alter_table( | |
| 13690 | my_core::TABLE *altered_table, my_core::Alter_inplace_info *ha_alter_info, | ||
| 13691 | bool commit, const dd::Table *old_table_def MY_ATTRIBUTE((__unused__)), | ||
| 13692 | dd::Table *new_table_def MY_ATTRIBUTE((__unused__))) { | ||
| 13693 |
1/2✓ Branch 0 taken 844 times.
✗ Branch 1 not taken.
|
844 | DBUG_ENTER_FUNC(); |
| 13694 | |||
| 13695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 844 times.
|
844 | assert(altered_table != nullptr); |
| 13696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 844 times.
|
844 | assert(ha_alter_info != nullptr); |
| 13697 | |||
| 13698 | 844 | Rdb_inplace_alter_ctx *const ctx0 = | |
| 13699 | static_cast<Rdb_inplace_alter_ctx *>(ha_alter_info->handler_ctx); | ||
| 13700 | |||
| 13701 |
3/6✓ Branch 0 taken 844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 844 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 844 times.
✗ Branch 5 not taken.
|
844 | DEBUG_SYNC(ha_thd(), "rocksdb.commit_in_place_alter_table"); |
| 13702 | |||
| 13703 | /* | ||
| 13704 | IMPORTANT: When rollback is requested, mysql will abort with | ||
| 13705 | an assertion failure. That means every failed commit during inplace alter | ||
| 13706 | table will result in a fatal error on the server. Indexes ongoing creation | ||
| 13707 | will be detected when the server restarts, and dropped. | ||
| 13708 | |||
| 13709 | For partitioned tables, a rollback call to this function (commit == false) | ||
| 13710 | is done for each partition. A successful commit call only executes once | ||
| 13711 | for all partitions. | ||
| 13712 | */ | ||
| 13713 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 564 times.
|
844 | if (!commit) { |
| 13714 | /* If ctx has not been created yet, nothing to do here */ | ||
| 13715 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 268 times.
|
280 | if (!ctx0) { |
| 13716 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 13717 | } | ||
| 13718 | |||
| 13719 | /* | ||
| 13720 | Cannot call destructor for Rdb_tbl_def directly because we don't want to | ||
| 13721 | erase the mappings inside the ddl_manager, as the old_key_descr is still | ||
| 13722 | using them. | ||
| 13723 | */ | ||
| 13724 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 240 times.
|
268 | if (ctx0->m_new_key_descr) { |
| 13725 | /* Delete the new key descriptors */ | ||
| 13726 |
2/2✓ Branch 0 taken 63 times.
✓ Branch 1 taken 28 times.
|
91 | for (uint i = 0; i < ctx0->m_new_tdef->m_key_count; i++) { |
| 13727 | 63 | ctx0->m_new_key_descr[i] = nullptr; | |
| 13728 | } | ||
| 13729 | |||
| 13730 |
3/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 28 times.
|
91 | delete[] ctx0->m_new_key_descr; |
| 13731 | 28 | ctx0->m_new_key_descr = nullptr; | |
| 13732 | 28 | ctx0->m_new_tdef->m_key_descr_arr = nullptr; | |
| 13733 | |||
| 13734 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | delete ctx0->m_new_tdef; |
| 13735 | } | ||
| 13736 | |||
| 13737 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 240 times.
|
268 | if (!ctx0->m_added_indexes.empty()) { |
| 13738 | 28 | auto first_index = ctx0->m_added_indexes.begin(); | |
| 13739 | auto local_dict_manager = | ||
| 13740 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | dict_manager.get_dict_manager_selector_non_const( |
| 13741 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | (*first_index)->get_gl_index_id().cf_id); |
| 13742 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 13743 | /* Remove uncommitted key definitons from ddl_manager */ | ||
| 13744 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | ddl_manager.remove_uncommitted_keydefs(ctx0->m_added_indexes); |
| 13745 | |||
| 13746 | 28 | std::unordered_set<GL_INDEX_ID> all_gl_index_ids; | |
| 13747 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | local_dict_manager->get_ongoing_create_indexes(&all_gl_index_ids); |
| 13748 | |||
| 13749 | 28 | std::unordered_set<GL_INDEX_ID> gl_index_ids; | |
| 13750 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 28 times.
|
59 | for (auto index : ctx0->m_added_indexes) { |
| 13751 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | auto gl_index_id = index->get_gl_index_id(); |
| 13752 |
3/4✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 6 times.
|
31 | if (all_gl_index_ids.find(gl_index_id) != all_gl_index_ids.end()) { |
| 13753 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | gl_index_ids.insert(gl_index_id); |
| 13754 | } | ||
| 13755 | 31 | } | |
| 13756 | |||
| 13757 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
|
28 | if (!gl_index_ids.empty()) { |
| 13758 | /* Rollback any partially created indexes of this table */ | ||
| 13759 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | local_dict_manager->rollback_ongoing_index_creation(gl_index_ids); |
| 13760 | } | ||
| 13761 | 28 | } | |
| 13762 | |||
| 13763 |
1/2✓ Branch 0 taken 268 times.
✗ Branch 1 not taken.
|
268 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 13764 | } | ||
| 13765 | |||
| 13766 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 564 times.
|
564 | assert(ctx0); |
| 13767 | |||
| 13768 | /* | ||
| 13769 | For partitioned tables, we need to commit all changes to all tables at | ||
| 13770 | once, unlike in the other inplace alter API methods. | ||
| 13771 | */ | ||
| 13772 | inplace_alter_handler_ctx **ctx_array; | ||
| 13773 | inplace_alter_handler_ctx *ctx_single[2]; | ||
| 13774 | |||
| 13775 |
2/2✓ Branch 0 taken 89 times.
✓ Branch 1 taken 475 times.
|
564 | if (ha_alter_info->group_commit_ctx) { |
| 13776 |
4/6✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
89 | DBUG_EXECUTE_IF("crash_during_index_creation_partition", DBUG_SUICIDE();); |
| 13777 | 86 | ctx_array = ha_alter_info->group_commit_ctx; | |
| 13778 | } else { | ||
| 13779 | 475 | ctx_single[0] = ctx0; | |
| 13780 | 475 | ctx_single[1] = nullptr; | |
| 13781 | 475 | ctx_array = ctx_single; | |
| 13782 | } | ||
| 13783 | |||
| 13784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 561 times.
|
561 | assert(ctx0 == ctx_array[0]); |
| 13785 | 561 | ha_alter_info->group_commit_ctx = nullptr; | |
| 13786 | uint table_default_cf_id = | ||
| 13787 |
1/2✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
|
561 | m_tbl_def->m_key_descr_arr[0]->get_gl_index_id().cf_id; |
| 13788 |
2/2✓ Branch 0 taken 414 times.
✓ Branch 1 taken 147 times.
|
561 | if (ha_alter_info->handler_flags & |
| 13789 | (my_core::Alter_inplace_info::DROP_INDEX | | ||
| 13790 | my_core::Alter_inplace_info::DROP_UNIQUE_INDEX | | ||
| 13791 | my_core::Alter_inplace_info::ADD_INDEX | | ||
| 13792 | my_core::Alter_inplace_info::ADD_UNIQUE_INDEX)) { | ||
| 13793 | auto local_dict_manager = | ||
| 13794 |
1/2✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
|
414 | dict_manager.get_dict_manager_selector_non_const(table_default_cf_id); |
| 13795 |
1/2✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
|
414 | const std::unique_ptr<rocksdb::WriteBatch> wb = local_dict_manager->begin(); |
| 13796 | 414 | rocksdb::WriteBatch *const batch = wb.get(); | |
| 13797 | 414 | std::unordered_set<GL_INDEX_ID> create_index_ids; | |
| 13798 | |||
| 13799 | 414 | m_tbl_def = ctx0->m_new_tdef; | |
| 13800 | 414 | m_key_descr_arr = m_tbl_def->m_key_descr_arr; | |
| 13801 |
1/2✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
|
414 | m_pk_descr = m_key_descr_arr[pk_index(altered_table, m_tbl_def)]; |
| 13802 | |||
| 13803 |
6/10✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 411 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
414 | DBUG_EXECUTE_IF("rocksdb_commit_alter_table", { |
| 13804 | static constexpr char act[] = | ||
| 13805 | "now signal ready_to_mark_cf_dropped_before_commit_alter_table " | ||
| 13806 | "wait_for mark_cf_dropped_done_before_commit_alter_table"; | ||
| 13807 | assert(!debug_sync_set_action(ha_thd(), STRING_WITH_LEN(act))); | ||
| 13808 | }); | ||
| 13809 | |||
| 13810 | { | ||
| 13811 |
1/2✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
|
414 | std::lock_guard<Rdb_dict_manager> dm_lock(*local_dict_manager); |
| 13812 |
2/2✓ Branch 0 taken 546 times.
✓ Branch 1 taken 414 times.
|
960 | for (inplace_alter_handler_ctx **pctx = ctx_array; *pctx; pctx++) { |
| 13813 | 546 | Rdb_inplace_alter_ctx *const ctx = | |
| 13814 | static_cast<Rdb_inplace_alter_ctx *>(*pctx); | ||
| 13815 | |||
| 13816 | /* Mark indexes to be dropped */ | ||
| 13817 |
1/2✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
|
546 | local_dict_manager->add_drop_index(ctx->m_dropped_index_ids, batch); |
| 13818 | |||
| 13819 |
2/2✓ Branch 0 taken 420 times.
✓ Branch 1 taken 546 times.
|
966 | for (const auto &index : ctx->m_added_indexes) { |
| 13820 |
2/4✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 420 times.
✗ Branch 3 not taken.
|
420 | create_index_ids.insert(index->get_gl_index_id()); |
| 13821 | } | ||
| 13822 | |||
| 13823 |
2/4✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 546 times.
|
546 | if (ddl_manager.put_and_write(ctx->m_new_tdef, batch)) { |
| 13824 | /* | ||
| 13825 | Failed to write new entry into data dictionary, this should never | ||
| 13826 | happen. | ||
| 13827 | */ | ||
| 13828 | ✗ | assert(0); | |
| 13829 | } | ||
| 13830 | |||
| 13831 | /* | ||
| 13832 | Remove uncommitted key definitons from ddl_manager, as they are now | ||
| 13833 | committed into the data dictionary. | ||
| 13834 | */ | ||
| 13835 |
1/2✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
|
546 | ddl_manager.remove_uncommitted_keydefs(ctx->m_added_indexes); |
| 13836 | } | ||
| 13837 | |||
| 13838 |
2/4✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 414 times.
|
414 | if (local_dict_manager->commit(batch)) { |
| 13839 | /* | ||
| 13840 | Should never reach here. We assume MyRocks will abort if commit | ||
| 13841 | fails. | ||
| 13842 | */ | ||
| 13843 | ✗ | assert(0); | |
| 13844 | } | ||
| 13845 | |||
| 13846 | /* Mark ongoing create indexes as finished/remove from data dictionary */ | ||
| 13847 |
1/2✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
|
414 | local_dict_manager->finish_indexes_operation( |
| 13848 | create_index_ids, Rdb_key_def::DDL_CREATE_INDEX_ONGOING); | ||
| 13849 | 414 | } | |
| 13850 | |||
| 13851 |
6/10✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 411 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
414 | DBUG_EXECUTE_IF("rocksdb_delete_index", { |
| 13852 | static constexpr char act[] = | ||
| 13853 | "now signal ready_to_mark_cf_dropped_after_commit_alter_table " | ||
| 13854 | "wait_for mark_cf_dropped_done_after_commit_alter_table"; | ||
| 13855 | assert(!debug_sync_set_action(ha_thd(), STRING_WITH_LEN(act))); | ||
| 13856 | }); | ||
| 13857 | |||
| 13858 |
1/2✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
|
414 | rdb_drop_idx_thread.signal(); |
| 13859 | |||
| 13860 |
4/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 411 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 414 times.
|
414 | if (rocksdb_table_stats_use_table_scan && !ctx0->m_added_indexes.empty()) { |
| 13861 | // If new indexes are created, add the table to the recalc queue | ||
| 13862 | // to calculate stats for new indexes | ||
| 13863 | ✗ | rdb_is_thread.add_index_stats_request(m_tbl_def->full_tablename()); | |
| 13864 | } | ||
| 13865 | 414 | } | |
| 13866 | |||
| 13867 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 507 times.
|
561 | if (ha_alter_info->handler_flags & |
| 13868 | (my_core::Alter_inplace_info::CHANGE_CREATE_OPTION)) { | ||
| 13869 | auto local_dict_manager = | ||
| 13870 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | dict_manager.get_dict_manager_selector_non_const(table_default_cf_id); |
| 13871 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | const std::unique_ptr<rocksdb::WriteBatch> wb = local_dict_manager->begin(); |
| 13872 | 54 | rocksdb::WriteBatch *const batch = wb.get(); | |
| 13873 | 54 | std::unordered_set<GL_INDEX_ID> create_index_ids; | |
| 13874 | |||
| 13875 | 54 | ulonglong auto_incr_val = ha_alter_info->create_info->auto_increment_value; | |
| 13876 | |||
| 13877 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 54 times.
|
144 | for (inplace_alter_handler_ctx **pctx = ctx_array; *pctx; pctx++) { |
| 13878 | 90 | Rdb_inplace_alter_ctx *const ctx = | |
| 13879 | static_cast<Rdb_inplace_alter_ctx *>(*pctx); | ||
| 13880 | 90 | auto_incr_val = std::max(auto_incr_val, ctx->m_max_auto_incr); | |
| 13881 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | local_dict_manager->put_auto_incr_val( |
| 13882 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | batch, ctx->m_new_tdef->get_autoincr_gl_index_id(), auto_incr_val, |
| 13883 | true /* overwrite */); | ||
| 13884 | 90 | ctx->m_new_tdef->m_auto_incr_val = auto_incr_val; | |
| 13885 | } | ||
| 13886 | |||
| 13887 |
2/4✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
|
54 | if (local_dict_manager->commit(batch)) { |
| 13888 | ✗ | assert(0); | |
| 13889 | } | ||
| 13890 | 54 | } | |
| 13891 | |||
| 13892 |
1/2✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
|
561 | DBUG_RETURN(HA_EXIT_SUCCESS); |
| 13893 | } | ||
| 13894 | |||
| 13895 | #define SHOW_FNAME(name) rocksdb_show_##name | ||
| 13896 | |||
| 13897 | #define DEF_SHOW_FUNC(name, key) \ | ||
| 13898 | static int SHOW_FNAME(name)(MYSQL_THD thd, SHOW_VAR * var, char *buff) { \ | ||
| 13899 | rocksdb_status_counters.name = \ | ||
| 13900 | rocksdb_stats->getTickerCount(rocksdb::key); \ | ||
| 13901 | var->type = SHOW_LONGLONG; \ | ||
| 13902 | var->value = (char *)&rocksdb_status_counters.name; \ | ||
| 13903 | return HA_EXIT_SUCCESS; \ | ||
| 13904 | } | ||
| 13905 | |||
| 13906 | #define DEF_STATUS_VAR(name) \ | ||
| 13907 | { "rocksdb_" #name, (char *)&SHOW_FNAME(name), SHOW_FUNC, SHOW_SCOPE_GLOBAL } | ||
| 13908 | |||
| 13909 | #define DEF_STATUS_VAR_PTR(name, ptr, option) \ | ||
| 13910 | { "rocksdb_" name, (char *)ptr, option, SHOW_SCOPE_GLOBAL } | ||
| 13911 | |||
| 13912 | #define DEF_STATUS_VAR_FUNC(name, ptr, option) \ | ||
| 13913 | { name, reinterpret_cast<char *>(ptr), option, SHOW_SCOPE_GLOBAL } | ||
| 13914 | |||
| 13915 | struct rocksdb_status_counters_t { | ||
| 13916 | uint64_t block_cache_miss; | ||
| 13917 | uint64_t block_cache_hit; | ||
| 13918 | uint64_t block_cache_add; | ||
| 13919 | uint64_t block_cache_add_failures; | ||
| 13920 | uint64_t block_cache_index_miss; | ||
| 13921 | uint64_t block_cache_index_hit; | ||
| 13922 | uint64_t block_cache_index_add; | ||
| 13923 | uint64_t block_cache_index_bytes_insert; | ||
| 13924 | uint64_t block_cache_index_bytes_evict; | ||
| 13925 | uint64_t block_cache_filter_miss; | ||
| 13926 | uint64_t block_cache_filter_hit; | ||
| 13927 | uint64_t block_cache_filter_add; | ||
| 13928 | uint64_t block_cache_filter_bytes_insert; | ||
| 13929 | uint64_t block_cache_filter_bytes_evict; | ||
| 13930 | uint64_t block_cache_bytes_read; | ||
| 13931 | uint64_t block_cache_bytes_write; | ||
| 13932 | uint64_t block_cache_data_bytes_insert; | ||
| 13933 | uint64_t block_cache_data_miss; | ||
| 13934 | uint64_t block_cache_data_hit; | ||
| 13935 | uint64_t block_cache_data_add; | ||
| 13936 | uint64_t bloom_filter_useful; | ||
| 13937 | uint64_t bloom_filter_full_positive; | ||
| 13938 | uint64_t bloom_filter_full_true_positive; | ||
| 13939 | uint64_t memtable_hit; | ||
| 13940 | uint64_t memtable_miss; | ||
| 13941 | uint64_t get_hit_l0; | ||
| 13942 | uint64_t get_hit_l1; | ||
| 13943 | uint64_t get_hit_l2_and_up; | ||
| 13944 | uint64_t compaction_key_drop_new; | ||
| 13945 | uint64_t compaction_key_drop_obsolete; | ||
| 13946 | uint64_t compaction_key_drop_user; | ||
| 13947 | uint64_t number_keys_written; | ||
| 13948 | uint64_t number_keys_read; | ||
| 13949 | uint64_t number_keys_updated; | ||
| 13950 | uint64_t bytes_written; | ||
| 13951 | uint64_t bytes_read; | ||
| 13952 | uint64_t number_db_seek; | ||
| 13953 | uint64_t number_db_seek_found; | ||
| 13954 | uint64_t number_db_next; | ||
| 13955 | uint64_t number_db_next_found; | ||
| 13956 | uint64_t number_db_prev; | ||
| 13957 | uint64_t number_db_prev_found; | ||
| 13958 | uint64_t iter_bytes_read; | ||
| 13959 | uint64_t no_file_closes; | ||
| 13960 | uint64_t no_file_opens; | ||
| 13961 | uint64_t no_file_errors; | ||
| 13962 | uint64_t stall_micros; | ||
| 13963 | uint64_t num_iterators; | ||
| 13964 | uint64_t number_multiget_get; | ||
| 13965 | uint64_t number_multiget_keys_read; | ||
| 13966 | uint64_t number_multiget_bytes_read; | ||
| 13967 | uint64_t number_deletes_filtered; | ||
| 13968 | uint64_t number_merge_failures; | ||
| 13969 | uint64_t bloom_filter_prefix_checked; | ||
| 13970 | uint64_t bloom_filter_prefix_useful; | ||
| 13971 | uint64_t number_reseeks_iteration; | ||
| 13972 | uint64_t get_updates_since_calls; | ||
| 13973 | uint64_t block_cache_compressed_miss; | ||
| 13974 | uint64_t block_cache_compressed_hit; | ||
| 13975 | uint64_t wal_synced; | ||
| 13976 | uint64_t wal_bytes; | ||
| 13977 | uint64_t write_self; | ||
| 13978 | uint64_t write_other; | ||
| 13979 | uint64_t write_timedout; | ||
| 13980 | uint64_t write_wal; | ||
| 13981 | uint64_t flush_write_bytes; | ||
| 13982 | uint64_t compact_read_bytes; | ||
| 13983 | uint64_t compact_write_bytes; | ||
| 13984 | uint64_t number_superversion_acquires; | ||
| 13985 | uint64_t number_superversion_releases; | ||
| 13986 | uint64_t number_superversion_cleanups; | ||
| 13987 | uint64_t number_block_not_compressed; | ||
| 13988 | }; | ||
| 13989 | |||
| 13990 | static rocksdb_status_counters_t rocksdb_status_counters; | ||
| 13991 | |||
| 13992 | 11912 | DEF_SHOW_FUNC(block_cache_miss, BLOCK_CACHE_MISS) | |
| 13993 | 11912 | DEF_SHOW_FUNC(block_cache_hit, BLOCK_CACHE_HIT) | |
| 13994 | 11912 | DEF_SHOW_FUNC(block_cache_add, BLOCK_CACHE_ADD) | |
| 13995 | 11912 | DEF_SHOW_FUNC(block_cache_add_failures, BLOCK_CACHE_ADD_FAILURES) | |
| 13996 | 11912 | DEF_SHOW_FUNC(block_cache_index_miss, BLOCK_CACHE_INDEX_MISS) | |
| 13997 | 11912 | DEF_SHOW_FUNC(block_cache_index_hit, BLOCK_CACHE_INDEX_HIT) | |
| 13998 | 11912 | DEF_SHOW_FUNC(block_cache_index_add, BLOCK_CACHE_INDEX_ADD) | |
| 13999 | 11912 | DEF_SHOW_FUNC(block_cache_index_bytes_insert, BLOCK_CACHE_INDEX_BYTES_INSERT) | |
| 14000 | 11912 | DEF_SHOW_FUNC(block_cache_index_bytes_evict, BLOCK_CACHE_INDEX_BYTES_EVICT) | |
| 14001 | 11912 | DEF_SHOW_FUNC(block_cache_filter_miss, BLOCK_CACHE_FILTER_MISS) | |
| 14002 | 11912 | DEF_SHOW_FUNC(block_cache_filter_hit, BLOCK_CACHE_FILTER_HIT) | |
| 14003 | 11912 | DEF_SHOW_FUNC(block_cache_filter_add, BLOCK_CACHE_FILTER_ADD) | |
| 14004 | 11912 | DEF_SHOW_FUNC(block_cache_filter_bytes_insert, BLOCK_CACHE_FILTER_BYTES_INSERT) | |
| 14005 | 11912 | DEF_SHOW_FUNC(block_cache_filter_bytes_evict, BLOCK_CACHE_FILTER_BYTES_EVICT) | |
| 14006 | 11912 | DEF_SHOW_FUNC(block_cache_bytes_read, BLOCK_CACHE_BYTES_READ) | |
| 14007 | 11912 | DEF_SHOW_FUNC(block_cache_bytes_write, BLOCK_CACHE_BYTES_WRITE) | |
| 14008 | 11912 | DEF_SHOW_FUNC(block_cache_data_bytes_insert, BLOCK_CACHE_DATA_BYTES_INSERT) | |
| 14009 | 11912 | DEF_SHOW_FUNC(block_cache_data_miss, BLOCK_CACHE_DATA_MISS) | |
| 14010 | 11912 | DEF_SHOW_FUNC(block_cache_data_hit, BLOCK_CACHE_DATA_HIT) | |
| 14011 | 11912 | DEF_SHOW_FUNC(block_cache_data_add, BLOCK_CACHE_DATA_ADD) | |
| 14012 | 11912 | DEF_SHOW_FUNC(bloom_filter_useful, BLOOM_FILTER_USEFUL) | |
| 14013 | 11912 | DEF_SHOW_FUNC(bloom_filter_full_positive, BLOOM_FILTER_FULL_POSITIVE) | |
| 14014 | 11912 | DEF_SHOW_FUNC(bloom_filter_full_true_positive, BLOOM_FILTER_FULL_TRUE_POSITIVE) | |
| 14015 | 11912 | DEF_SHOW_FUNC(memtable_hit, MEMTABLE_HIT) | |
| 14016 | 11912 | DEF_SHOW_FUNC(memtable_miss, MEMTABLE_MISS) | |
| 14017 | 11912 | DEF_SHOW_FUNC(get_hit_l0, GET_HIT_L0) | |
| 14018 | 11912 | DEF_SHOW_FUNC(get_hit_l1, GET_HIT_L1) | |
| 14019 | 11912 | DEF_SHOW_FUNC(get_hit_l2_and_up, GET_HIT_L2_AND_UP) | |
| 14020 | 11912 | DEF_SHOW_FUNC(compaction_key_drop_new, COMPACTION_KEY_DROP_NEWER_ENTRY) | |
| 14021 | 11912 | DEF_SHOW_FUNC(compaction_key_drop_obsolete, COMPACTION_KEY_DROP_OBSOLETE) | |
| 14022 | 11912 | DEF_SHOW_FUNC(compaction_key_drop_user, COMPACTION_KEY_DROP_USER) | |
| 14023 | 11912 | DEF_SHOW_FUNC(number_keys_written, NUMBER_KEYS_WRITTEN) | |
| 14024 | 11912 | DEF_SHOW_FUNC(number_keys_read, NUMBER_KEYS_READ) | |
| 14025 | 11912 | DEF_SHOW_FUNC(number_keys_updated, NUMBER_KEYS_UPDATED) | |
| 14026 | 11912 | DEF_SHOW_FUNC(bytes_written, BYTES_WRITTEN) | |
| 14027 | 11912 | DEF_SHOW_FUNC(bytes_read, BYTES_READ) | |
| 14028 | 11912 | DEF_SHOW_FUNC(number_db_seek, NUMBER_DB_SEEK) | |
| 14029 | 11912 | DEF_SHOW_FUNC(number_db_seek_found, NUMBER_DB_SEEK_FOUND) | |
| 14030 | 11912 | DEF_SHOW_FUNC(number_db_next, NUMBER_DB_NEXT) | |
| 14031 | 11912 | DEF_SHOW_FUNC(number_db_next_found, NUMBER_DB_NEXT_FOUND) | |
| 14032 | 11912 | DEF_SHOW_FUNC(number_db_prev, NUMBER_DB_PREV) | |
| 14033 | 11912 | DEF_SHOW_FUNC(number_db_prev_found, NUMBER_DB_PREV_FOUND) | |
| 14034 | 11912 | DEF_SHOW_FUNC(iter_bytes_read, ITER_BYTES_READ) | |
| 14035 | 11912 | DEF_SHOW_FUNC(no_file_closes, NO_FILE_CLOSES) | |
| 14036 | 11912 | DEF_SHOW_FUNC(no_file_opens, NO_FILE_OPENS) | |
| 14037 | 11912 | DEF_SHOW_FUNC(no_file_errors, NO_FILE_ERRORS) | |
| 14038 | 11912 | DEF_SHOW_FUNC(stall_micros, STALL_MICROS) | |
| 14039 | 11912 | DEF_SHOW_FUNC(num_iterators, NO_ITERATORS) | |
| 14040 | 11912 | DEF_SHOW_FUNC(number_multiget_get, NUMBER_MULTIGET_CALLS) | |
| 14041 | 11912 | DEF_SHOW_FUNC(number_multiget_keys_read, NUMBER_MULTIGET_KEYS_READ) | |
| 14042 | 11912 | DEF_SHOW_FUNC(number_multiget_bytes_read, NUMBER_MULTIGET_BYTES_READ) | |
| 14043 | 11912 | DEF_SHOW_FUNC(number_deletes_filtered, NUMBER_FILTERED_DELETES) | |
| 14044 | 11912 | DEF_SHOW_FUNC(number_merge_failures, NUMBER_MERGE_FAILURES) | |
| 14045 | 11912 | DEF_SHOW_FUNC(bloom_filter_prefix_checked, BLOOM_FILTER_PREFIX_CHECKED) | |
| 14046 | 11912 | DEF_SHOW_FUNC(bloom_filter_prefix_useful, BLOOM_FILTER_PREFIX_USEFUL) | |
| 14047 | 11912 | DEF_SHOW_FUNC(number_reseeks_iteration, NUMBER_OF_RESEEKS_IN_ITERATION) | |
| 14048 | 11912 | DEF_SHOW_FUNC(get_updates_since_calls, GET_UPDATES_SINCE_CALLS) | |
| 14049 | 11912 | DEF_SHOW_FUNC(block_cache_compressed_miss, BLOCK_CACHE_COMPRESSED_MISS) | |
| 14050 | 11912 | DEF_SHOW_FUNC(block_cache_compressed_hit, BLOCK_CACHE_COMPRESSED_HIT) | |
| 14051 | 11912 | DEF_SHOW_FUNC(wal_synced, WAL_FILE_SYNCED) | |
| 14052 | 11912 | DEF_SHOW_FUNC(wal_bytes, WAL_FILE_BYTES) | |
| 14053 | 11912 | DEF_SHOW_FUNC(write_self, WRITE_DONE_BY_SELF) | |
| 14054 | 11912 | DEF_SHOW_FUNC(write_other, WRITE_DONE_BY_OTHER) | |
| 14055 | 11912 | DEF_SHOW_FUNC(write_timedout, WRITE_TIMEDOUT) | |
| 14056 | 11912 | DEF_SHOW_FUNC(write_wal, WRITE_WITH_WAL) | |
| 14057 | 11912 | DEF_SHOW_FUNC(flush_write_bytes, FLUSH_WRITE_BYTES) | |
| 14058 | 11912 | DEF_SHOW_FUNC(compact_read_bytes, COMPACT_READ_BYTES) | |
| 14059 | 11912 | DEF_SHOW_FUNC(compact_write_bytes, COMPACT_WRITE_BYTES) | |
| 14060 | 11912 | DEF_SHOW_FUNC(number_superversion_acquires, NUMBER_SUPERVERSION_ACQUIRES) | |
| 14061 | 11912 | DEF_SHOW_FUNC(number_superversion_releases, NUMBER_SUPERVERSION_RELEASES) | |
| 14062 | 11912 | DEF_SHOW_FUNC(number_superversion_cleanups, NUMBER_SUPERVERSION_CLEANUPS) | |
| 14063 | 11912 | DEF_SHOW_FUNC(number_block_not_compressed, NUMBER_BLOCK_NOT_COMPRESSED) | |
| 14064 | |||
| 14065 | 11912 | static void myrocks_update_status() { | |
| 14066 | 11912 | export_stats.rows_deleted = global_stats.rows[ROWS_DELETED]; | |
| 14067 | 11912 | export_stats.rows_deleted_blind = global_stats.rows[ROWS_DELETED_BLIND]; | |
| 14068 | 11912 | export_stats.rows_inserted = global_stats.rows[ROWS_INSERTED]; | |
| 14069 | 11912 | export_stats.rows_read = global_stats.rows[ROWS_READ]; | |
| 14070 | 11912 | export_stats.rows_updated = global_stats.rows[ROWS_UPDATED]; | |
| 14071 | 11912 | export_stats.rows_expired = global_stats.rows[ROWS_EXPIRED]; | |
| 14072 | 11912 | export_stats.rows_filtered = global_stats.rows[ROWS_FILTERED]; | |
| 14073 | 11912 | export_stats.rows_unfiltered_no_snapshot = | |
| 14074 | 11912 | global_stats.rows[ROWS_UNFILTERED_NO_SNAPSHOT]; | |
| 14075 | |||
| 14076 | 11912 | export_stats.system_rows_deleted = global_stats.system_rows[ROWS_DELETED]; | |
| 14077 | 11912 | export_stats.system_rows_inserted = global_stats.system_rows[ROWS_INSERTED]; | |
| 14078 | 11912 | export_stats.system_rows_read = global_stats.system_rows[ROWS_READ]; | |
| 14079 | 11912 | export_stats.system_rows_updated = global_stats.system_rows[ROWS_UPDATED]; | |
| 14080 | |||
| 14081 | 11912 | export_stats.queries_point = global_stats.queries[QUERIES_POINT]; | |
| 14082 | 11912 | export_stats.queries_range = global_stats.queries[QUERIES_RANGE]; | |
| 14083 | |||
| 14084 | 11912 | export_stats.table_index_stats_success = | |
| 14085 | 11912 | global_stats.table_index_stats_result[TABLE_INDEX_STATS_SUCCESS]; | |
| 14086 | 11912 | export_stats.table_index_stats_failure = | |
| 14087 | 11912 | global_stats.table_index_stats_result[TABLE_INDEX_STATS_FAILURE]; | |
| 14088 | 11912 | export_stats.table_index_stats_req_queue_length = | |
| 14089 | 11912 | rdb_is_thread.get_request_queue_size(); | |
| 14090 | |||
| 14091 | 11912 | export_stats.covered_secondary_key_lookups = | |
| 14092 | 11912 | global_stats.covered_secondary_key_lookups; | |
| 14093 | 11912 | } | |
| 14094 | |||
| 14095 | 11912 | static void myrocks_update_memory_status() { | |
| 14096 | 11912 | std::vector<rocksdb::DB *> dbs; | |
| 14097 | 11912 | std::unordered_set<const rocksdb::Cache *> cache_set; | |
| 14098 |
1/2✓ Branch 0 taken 11912 times.
✗ Branch 1 not taken.
|
11912 | dbs.push_back(rdb); |
| 14099 | 11912 | std::map<rocksdb::MemoryUtil::UsageType, uint64_t> temp_usage_by_type; | |
| 14100 |
2/4✓ Branch 0 taken 11912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11912 times.
✗ Branch 3 not taken.
|
11912 | rocksdb::MemoryUtil::GetApproximateMemoryUsageByType(dbs, cache_set, |
| 14101 | &temp_usage_by_type); | ||
| 14102 | 11912 | memory_stats.memtable_total = | |
| 14103 |
1/2✓ Branch 0 taken 11912 times.
✗ Branch 1 not taken.
|
11912 | temp_usage_by_type[rocksdb::MemoryUtil::kMemTableTotal]; |
| 14104 | 11912 | memory_stats.memtable_unflushed = | |
| 14105 |
1/2✓ Branch 0 taken 11912 times.
✗ Branch 1 not taken.
|
11912 | temp_usage_by_type[rocksdb::MemoryUtil::kMemTableUnFlushed]; |
| 14106 | 11912 | } | |
| 14107 | |||
| 14108 | static SHOW_VAR myrocks_status_variables[] = { | ||
| 14109 | DEF_STATUS_VAR_FUNC("rows_deleted", &export_stats.rows_deleted, | ||
| 14110 | SHOW_LONGLONG), | ||
| 14111 | DEF_STATUS_VAR_FUNC("rows_deleted_blind", &export_stats.rows_deleted_blind, | ||
| 14112 | SHOW_LONGLONG), | ||
| 14113 | DEF_STATUS_VAR_FUNC("rows_inserted", &export_stats.rows_inserted, | ||
| 14114 | SHOW_LONGLONG), | ||
| 14115 | DEF_STATUS_VAR_FUNC("rows_read", &export_stats.rows_read, SHOW_LONGLONG), | ||
| 14116 | DEF_STATUS_VAR_FUNC("rows_updated", &export_stats.rows_updated, | ||
| 14117 | SHOW_LONGLONG), | ||
| 14118 | DEF_STATUS_VAR_FUNC("rows_expired", &export_stats.rows_expired, | ||
| 14119 | SHOW_LONGLONG), | ||
| 14120 | DEF_STATUS_VAR_FUNC("rows_filtered", &export_stats.rows_filtered, | ||
| 14121 | SHOW_LONGLONG), | ||
| 14122 | DEF_STATUS_VAR_FUNC("rows_unfiltered_no_snapshot", | ||
| 14123 | &export_stats.rows_unfiltered_no_snapshot, | ||
| 14124 | SHOW_LONGLONG), | ||
| 14125 | DEF_STATUS_VAR_FUNC("system_rows_deleted", | ||
| 14126 | &export_stats.system_rows_deleted, SHOW_LONGLONG), | ||
| 14127 | DEF_STATUS_VAR_FUNC("system_rows_inserted", | ||
| 14128 | &export_stats.system_rows_inserted, SHOW_LONGLONG), | ||
| 14129 | DEF_STATUS_VAR_FUNC("system_rows_read", &export_stats.system_rows_read, | ||
| 14130 | SHOW_LONGLONG), | ||
| 14131 | DEF_STATUS_VAR_FUNC("system_rows_updated", | ||
| 14132 | &export_stats.system_rows_updated, SHOW_LONGLONG), | ||
| 14133 | DEF_STATUS_VAR_FUNC("memtable_total", &memory_stats.memtable_total, | ||
| 14134 | SHOW_LONGLONG), | ||
| 14135 | DEF_STATUS_VAR_FUNC("memtable_unflushed", &memory_stats.memtable_unflushed, | ||
| 14136 | SHOW_LONGLONG), | ||
| 14137 | DEF_STATUS_VAR_FUNC("queries_point", &export_stats.queries_point, | ||
| 14138 | SHOW_LONGLONG), | ||
| 14139 | DEF_STATUS_VAR_FUNC("queries_range", &export_stats.queries_range, | ||
| 14140 | SHOW_LONGLONG), | ||
| 14141 | DEF_STATUS_VAR_FUNC("table_index_stats_success", | ||
| 14142 | &export_stats.table_index_stats_success, SHOW_LONGLONG), | ||
| 14143 | DEF_STATUS_VAR_FUNC("table_index_stats_failure", | ||
| 14144 | &export_stats.table_index_stats_failure, SHOW_LONGLONG), | ||
| 14145 | DEF_STATUS_VAR_FUNC("table_index_stats_req_queue_length", | ||
| 14146 | &export_stats.table_index_stats_req_queue_length, | ||
| 14147 | SHOW_LONGLONG), | ||
| 14148 | DEF_STATUS_VAR_FUNC("covered_secondary_key_lookups", | ||
| 14149 | &export_stats.covered_secondary_key_lookups, | ||
| 14150 | SHOW_LONGLONG), | ||
| 14151 | |||
| 14152 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 14153 | |||
| 14154 | 11912 | static void show_myrocks_vars(THD *thd, SHOW_VAR *var, char *buff) { | |
| 14155 | 11912 | myrocks_update_status(); | |
| 14156 | 11912 | myrocks_update_memory_status(); | |
| 14157 | 11912 | var->type = SHOW_ARRAY; | |
| 14158 | 11912 | var->value = reinterpret_cast<char *>(&myrocks_status_variables); | |
| 14159 | 11912 | } | |
| 14160 | |||
| 14161 | 552760 | static ulonglong io_stall_prop_value( | |
| 14162 | const std::map<std::string, std::string> &props, const std::string &key) { | ||
| 14163 | std::map<std::string, std::string>::const_iterator iter = | ||
| 14164 |
2/4✓ Branch 0 taken 552760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 552760 times.
✗ Branch 3 not taken.
|
552760 | props.find("io_stalls." + key); |
| 14165 |
1/2✓ Branch 0 taken 552760 times.
✗ Branch 1 not taken.
|
552760 | if (iter != props.end()) { |
| 14166 |
1/2✓ Branch 0 taken 552760 times.
✗ Branch 1 not taken.
|
552760 | return std::stoull(iter->second); |
| 14167 | } else { | ||
| 14168 | ✗ | DBUG_PRINT("warning", | |
| 14169 | ("RocksDB GetMapProperty hasn't returned key=%s", key.c_str())); | ||
| 14170 | ✗ | assert(0); | |
| 14171 | return 0; | ||
| 14172 | } | ||
| 14173 | } | ||
| 14174 | |||
| 14175 | 11912 | static void update_rocksdb_stall_status() { | |
| 14176 | 11912 | st_io_stall_stats local_io_stall_stats; | |
| 14177 |
3/4✓ Branch 0 taken 11912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✓ Branch 3 taken 11912 times.
|
67188 | for (const auto &cf_name : cf_manager.get_cf_names()) { |
| 14178 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 14179 |
1/2✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
|
55276 | cf_manager.get_cf(cf_name); |
| 14180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55276 times.
|
55276 | if (!cfh) { |
| 14181 | ✗ | continue; | |
| 14182 | } | ||
| 14183 | |||
| 14184 | // Retrieve information from valid CF handle object. It is safe | ||
| 14185 | // even if the CF is removed from cf_manager at this point. | ||
| 14186 | 55276 | std::map<std::string, std::string> props; | |
| 14187 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 55276 times.
|
55276 | if (!rdb->GetMapProperty(cfh.get(), "rocksdb.cfstats", &props)) { |
| 14188 | ✗ | continue; | |
| 14189 | } | ||
| 14190 | |||
| 14191 | 55276 | local_io_stall_stats.level0_slowdown += | |
| 14192 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "level0_slowdown"); |
| 14193 | 55276 | local_io_stall_stats.level0_slowdown_with_compaction += | |
| 14194 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "level0_slowdown_with_compaction"); |
| 14195 | 55276 | local_io_stall_stats.level0_numfiles += | |
| 14196 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "level0_numfiles"); |
| 14197 | 55276 | local_io_stall_stats.level0_numfiles_with_compaction += | |
| 14198 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "level0_numfiles_with_compaction"); |
| 14199 | 55276 | local_io_stall_stats.stop_for_pending_compaction_bytes += | |
| 14200 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "stop_for_pending_compaction_bytes"); |
| 14201 | 55276 | local_io_stall_stats.slowdown_for_pending_compaction_bytes += | |
| 14202 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "slowdown_for_pending_compaction_bytes"); |
| 14203 | 55276 | local_io_stall_stats.memtable_compaction += | |
| 14204 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "memtable_compaction"); |
| 14205 | 55276 | local_io_stall_stats.memtable_slowdown += | |
| 14206 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "memtable_slowdown"); |
| 14207 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | local_io_stall_stats.total_stop += io_stall_prop_value(props, "total_stop"); |
| 14208 | 55276 | local_io_stall_stats.total_slowdown += | |
| 14209 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
55276 | io_stall_prop_value(props, "total_slowdown"); |
| 14210 |
2/4✓ Branch 0 taken 55276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55276 times.
✗ Branch 3 not taken.
|
67188 | } |
| 14211 | 11912 | io_stall_stats = local_io_stall_stats; | |
| 14212 | 11912 | } | |
| 14213 | |||
| 14214 | static SHOW_VAR rocksdb_stall_status_variables[] = { | ||
| 14215 | DEF_STATUS_VAR_FUNC("l0_file_count_limit_slowdowns", | ||
| 14216 | &io_stall_stats.level0_slowdown, SHOW_LONGLONG), | ||
| 14217 | DEF_STATUS_VAR_FUNC("locked_l0_file_count_limit_slowdowns", | ||
| 14218 | &io_stall_stats.level0_slowdown_with_compaction, | ||
| 14219 | SHOW_LONGLONG), | ||
| 14220 | DEF_STATUS_VAR_FUNC("l0_file_count_limit_stops", | ||
| 14221 | &io_stall_stats.level0_numfiles, SHOW_LONGLONG), | ||
| 14222 | DEF_STATUS_VAR_FUNC("locked_l0_file_count_limit_stops", | ||
| 14223 | &io_stall_stats.level0_numfiles_with_compaction, | ||
| 14224 | SHOW_LONGLONG), | ||
| 14225 | DEF_STATUS_VAR_FUNC("pending_compaction_limit_stops", | ||
| 14226 | &io_stall_stats.stop_for_pending_compaction_bytes, | ||
| 14227 | SHOW_LONGLONG), | ||
| 14228 | DEF_STATUS_VAR_FUNC("pending_compaction_limit_slowdowns", | ||
| 14229 | &io_stall_stats.slowdown_for_pending_compaction_bytes, | ||
| 14230 | SHOW_LONGLONG), | ||
| 14231 | DEF_STATUS_VAR_FUNC("memtable_limit_stops", | ||
| 14232 | &io_stall_stats.memtable_compaction, SHOW_LONGLONG), | ||
| 14233 | DEF_STATUS_VAR_FUNC("memtable_limit_slowdowns", | ||
| 14234 | &io_stall_stats.memtable_slowdown, SHOW_LONGLONG), | ||
| 14235 | DEF_STATUS_VAR_FUNC("total_stops", &io_stall_stats.total_stop, | ||
| 14236 | SHOW_LONGLONG), | ||
| 14237 | DEF_STATUS_VAR_FUNC("total_slowdowns", &io_stall_stats.total_slowdown, | ||
| 14238 | SHOW_LONGLONG), | ||
| 14239 | // end of the array marker | ||
| 14240 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 14241 | |||
| 14242 | 11912 | static void show_rocksdb_stall_vars(THD *thd, SHOW_VAR *var, char *buff) { | |
| 14243 | 11912 | update_rocksdb_stall_status(); | |
| 14244 | 11912 | var->type = SHOW_ARRAY; | |
| 14245 | 11912 | var->value = reinterpret_cast<char *>(&rocksdb_stall_status_variables); | |
| 14246 | 11912 | } | |
| 14247 | |||
| 14248 | static SHOW_VAR rocksdb_status_vars[] = { | ||
| 14249 | DEF_STATUS_VAR(block_cache_miss), | ||
| 14250 | DEF_STATUS_VAR(block_cache_hit), | ||
| 14251 | DEF_STATUS_VAR(block_cache_add), | ||
| 14252 | DEF_STATUS_VAR(block_cache_add_failures), | ||
| 14253 | DEF_STATUS_VAR(block_cache_index_miss), | ||
| 14254 | DEF_STATUS_VAR(block_cache_index_hit), | ||
| 14255 | DEF_STATUS_VAR(block_cache_index_add), | ||
| 14256 | DEF_STATUS_VAR(block_cache_index_bytes_insert), | ||
| 14257 | DEF_STATUS_VAR(block_cache_index_bytes_evict), | ||
| 14258 | DEF_STATUS_VAR(block_cache_filter_miss), | ||
| 14259 | DEF_STATUS_VAR(block_cache_filter_hit), | ||
| 14260 | DEF_STATUS_VAR(block_cache_filter_add), | ||
| 14261 | DEF_STATUS_VAR(block_cache_filter_bytes_insert), | ||
| 14262 | DEF_STATUS_VAR(block_cache_filter_bytes_evict), | ||
| 14263 | DEF_STATUS_VAR(block_cache_bytes_read), | ||
| 14264 | DEF_STATUS_VAR(block_cache_bytes_write), | ||
| 14265 | DEF_STATUS_VAR(block_cache_data_bytes_insert), | ||
| 14266 | DEF_STATUS_VAR(block_cache_data_miss), | ||
| 14267 | DEF_STATUS_VAR(block_cache_data_hit), | ||
| 14268 | DEF_STATUS_VAR(block_cache_data_add), | ||
| 14269 | DEF_STATUS_VAR(bloom_filter_useful), | ||
| 14270 | DEF_STATUS_VAR(bloom_filter_full_positive), | ||
| 14271 | DEF_STATUS_VAR(bloom_filter_full_true_positive), | ||
| 14272 | DEF_STATUS_VAR(memtable_hit), | ||
| 14273 | DEF_STATUS_VAR(memtable_miss), | ||
| 14274 | DEF_STATUS_VAR(get_hit_l0), | ||
| 14275 | DEF_STATUS_VAR(get_hit_l1), | ||
| 14276 | DEF_STATUS_VAR(get_hit_l2_and_up), | ||
| 14277 | DEF_STATUS_VAR(compaction_key_drop_new), | ||
| 14278 | DEF_STATUS_VAR(compaction_key_drop_obsolete), | ||
| 14279 | DEF_STATUS_VAR(compaction_key_drop_user), | ||
| 14280 | DEF_STATUS_VAR(number_keys_written), | ||
| 14281 | DEF_STATUS_VAR(number_keys_read), | ||
| 14282 | DEF_STATUS_VAR(number_keys_updated), | ||
| 14283 | DEF_STATUS_VAR(bytes_written), | ||
| 14284 | DEF_STATUS_VAR(bytes_read), | ||
| 14285 | DEF_STATUS_VAR(number_db_seek), | ||
| 14286 | DEF_STATUS_VAR(number_db_seek_found), | ||
| 14287 | DEF_STATUS_VAR(number_db_next), | ||
| 14288 | DEF_STATUS_VAR(number_db_next_found), | ||
| 14289 | DEF_STATUS_VAR(number_db_prev), | ||
| 14290 | DEF_STATUS_VAR(number_db_prev_found), | ||
| 14291 | DEF_STATUS_VAR(iter_bytes_read), | ||
| 14292 | DEF_STATUS_VAR(no_file_closes), | ||
| 14293 | DEF_STATUS_VAR(no_file_opens), | ||
| 14294 | DEF_STATUS_VAR(no_file_errors), | ||
| 14295 | DEF_STATUS_VAR(stall_micros), | ||
| 14296 | DEF_STATUS_VAR(num_iterators), | ||
| 14297 | DEF_STATUS_VAR(number_multiget_get), | ||
| 14298 | DEF_STATUS_VAR(number_multiget_keys_read), | ||
| 14299 | DEF_STATUS_VAR(number_multiget_bytes_read), | ||
| 14300 | DEF_STATUS_VAR(number_deletes_filtered), | ||
| 14301 | DEF_STATUS_VAR(number_merge_failures), | ||
| 14302 | DEF_STATUS_VAR(bloom_filter_prefix_checked), | ||
| 14303 | DEF_STATUS_VAR(bloom_filter_prefix_useful), | ||
| 14304 | DEF_STATUS_VAR(number_reseeks_iteration), | ||
| 14305 | DEF_STATUS_VAR(get_updates_since_calls), | ||
| 14306 | DEF_STATUS_VAR(block_cache_compressed_miss), | ||
| 14307 | DEF_STATUS_VAR(block_cache_compressed_hit), | ||
| 14308 | DEF_STATUS_VAR(wal_synced), | ||
| 14309 | DEF_STATUS_VAR(wal_bytes), | ||
| 14310 | DEF_STATUS_VAR(write_self), | ||
| 14311 | DEF_STATUS_VAR(write_other), | ||
| 14312 | DEF_STATUS_VAR(write_timedout), | ||
| 14313 | DEF_STATUS_VAR(write_wal), | ||
| 14314 | DEF_STATUS_VAR(flush_write_bytes), | ||
| 14315 | DEF_STATUS_VAR(compact_read_bytes), | ||
| 14316 | DEF_STATUS_VAR(compact_write_bytes), | ||
| 14317 | DEF_STATUS_VAR(number_superversion_acquires), | ||
| 14318 | DEF_STATUS_VAR(number_superversion_releases), | ||
| 14319 | DEF_STATUS_VAR(number_superversion_cleanups), | ||
| 14320 | DEF_STATUS_VAR(number_block_not_compressed), | ||
| 14321 | DEF_STATUS_VAR_PTR("row_lock_deadlocks", &rocksdb_row_lock_deadlocks, | ||
| 14322 | SHOW_LONGLONG), | ||
| 14323 | DEF_STATUS_VAR_PTR("row_lock_wait_timeouts", | ||
| 14324 | &rocksdb_row_lock_wait_timeouts, SHOW_LONGLONG), | ||
| 14325 | DEF_STATUS_VAR_PTR("snapshot_conflict_errors", | ||
| 14326 | &rocksdb_snapshot_conflict_errors, SHOW_LONGLONG), | ||
| 14327 | DEF_STATUS_VAR_PTR("wal_group_syncs", &rocksdb_wal_group_syncs, | ||
| 14328 | SHOW_LONGLONG), | ||
| 14329 | DEF_STATUS_VAR_PTR("manual_compactions_processed", | ||
| 14330 | &rocksdb_manual_compactions_processed, SHOW_LONGLONG), | ||
| 14331 | DEF_STATUS_VAR_PTR("manual_compactions_cancelled", | ||
| 14332 | &rocksdb_manual_compactions_cancelled, SHOW_LONGLONG), | ||
| 14333 | DEF_STATUS_VAR_PTR("manual_compactions_running", | ||
| 14334 | &rocksdb_manual_compactions_running, SHOW_LONGLONG), | ||
| 14335 | DEF_STATUS_VAR_PTR("manual_compactions_pending", | ||
| 14336 | &rocksdb_manual_compactions_pending, SHOW_LONGLONG), | ||
| 14337 | DEF_STATUS_VAR_PTR("number_sst_entry_put", &rocksdb_num_sst_entry_put, | ||
| 14338 | SHOW_LONGLONG), | ||
| 14339 | DEF_STATUS_VAR_PTR("number_sst_entry_delete", &rocksdb_num_sst_entry_delete, | ||
| 14340 | SHOW_LONGLONG), | ||
| 14341 | DEF_STATUS_VAR_PTR("number_sst_entry_singledelete", | ||
| 14342 | &rocksdb_num_sst_entry_singledelete, SHOW_LONGLONG), | ||
| 14343 | DEF_STATUS_VAR_PTR("number_sst_entry_merge", &rocksdb_num_sst_entry_merge, | ||
| 14344 | SHOW_LONGLONG), | ||
| 14345 | DEF_STATUS_VAR_PTR("number_sst_entry_other", &rocksdb_num_sst_entry_other, | ||
| 14346 | SHOW_LONGLONG), | ||
| 14347 | DEF_STATUS_VAR_PTR("additional_compaction_triggers", | ||
| 14348 | &rocksdb_additional_compaction_triggers, SHOW_LONGLONG), | ||
| 14349 | #ifndef NDEBUG | ||
| 14350 | DEF_STATUS_VAR_PTR("num_get_for_update_calls", | ||
| 14351 | &rocksdb_num_get_for_update_calls, SHOW_LONGLONG), | ||
| 14352 | #endif | ||
| 14353 | DEF_STATUS_VAR_PTR("partial_index_groups_sorted", | ||
| 14354 | &rocksdb_partial_index_groups_sorted, SHOW_LONGLONG), | ||
| 14355 | DEF_STATUS_VAR_PTR("partial_index_groups_materialized", | ||
| 14356 | &rocksdb_partial_index_groups_materialized, | ||
| 14357 | SHOW_LONGLONG), | ||
| 14358 | DEF_STATUS_VAR_PTR("partial_index_rows_sorted", | ||
| 14359 | &rocksdb_partial_index_rows_sorted, SHOW_LONGLONG), | ||
| 14360 | DEF_STATUS_VAR_PTR("partial_index_rows_materialized", | ||
| 14361 | &rocksdb_partial_index_rows_materialized, SHOW_LONGLONG), | ||
| 14362 | |||
| 14363 | // the variables generated by SHOW_FUNC are sorted only by prefix (first | ||
| 14364 | // arg in the tuple below), so make sure it is unique to make sorting | ||
| 14365 | // deterministic as quick sort is not stable | ||
| 14366 | {"rocksdb", reinterpret_cast<char *>(&show_myrocks_vars), SHOW_FUNC, | ||
| 14367 | SHOW_SCOPE_GLOBAL}, | ||
| 14368 | {"rocksdb_stall", reinterpret_cast<char *>(&show_rocksdb_stall_vars), | ||
| 14369 | SHOW_FUNC, SHOW_SCOPE_GLOBAL}, | ||
| 14370 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 14371 | |||
| 14372 | /* | ||
| 14373 | Background thread's main logic | ||
| 14374 | */ | ||
| 14375 | |||
| 14376 | 902 | void Rdb_background_thread::run() { | |
| 14377 | // How many seconds to wait till flushing the WAL next time. | ||
| 14378 | 902 | const int WAKE_UP_INTERVAL = 1; | |
| 14379 | |||
| 14380 | timespec ts_next_sync; | ||
| 14381 | 902 | clock_gettime(CLOCK_REALTIME, &ts_next_sync); | |
| 14382 | 902 | ts_next_sync.tv_sec += WAKE_UP_INTERVAL; | |
| 14383 | |||
| 14384 | for (;;) { | ||
| 14385 | // Wait until the next timeout or until we receive a signal to stop the | ||
| 14386 | // thread. Request to stop the thread should only be triggered when the | ||
| 14387 | // storage engine is being unloaded. | ||
| 14388 |
2/4✓ Branch 0 taken 184349 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 184349 times.
✗ Branch 3 not taken.
|
184349 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 14389 | const auto ret MY_ATTRIBUTE((__unused__)) = | ||
| 14390 |
1/2✓ Branch 0 taken 184313 times.
✗ Branch 1 not taken.
|
184349 | mysql_cond_timedwait(&m_signal_cond, &m_signal_mutex, &ts_next_sync); |
| 14391 | |||
| 14392 | // Check that we receive only the expected error codes. | ||
| 14393 |
3/4✓ Branch 0 taken 183447 times.
✓ Branch 1 taken 866 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 183447 times.
|
184313 | assert(ret == 0 || ret == ETIMEDOUT); |
| 14394 | 184313 | const std::atomic<THD::killed_state> local_killed(m_killed.load()); | |
| 14395 | 184313 | const bool local_save_stats = m_save_stats; | |
| 14396 | 184313 | reset(); | |
| 14397 |
2/4✓ Branch 0 taken 184313 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 184313 times.
✗ Branch 3 not taken.
|
184313 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 14398 | |||
| 14399 |
2/2✓ Branch 0 taken 866 times.
✓ Branch 1 taken 183447 times.
|
184313 | if (local_killed) { |
| 14400 | // If we're here then that's because condition variable was signaled by | ||
| 14401 | // another thread and we're shutting down. Break out the loop to make | ||
| 14402 | // sure that shutdown thread can proceed. | ||
| 14403 | 866 | break; | |
| 14404 | } | ||
| 14405 | |||
| 14406 | // This path should be taken only when the timer expired. | ||
| 14407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 183447 times.
|
183447 | assert(ret == ETIMEDOUT); |
| 14408 | |||
| 14409 |
2/2✓ Branch 0 taken 8791 times.
✓ Branch 1 taken 174656 times.
|
183447 | if (local_save_stats) { |
| 14410 |
1/2✓ Branch 0 taken 8791 times.
✗ Branch 1 not taken.
|
8791 | ddl_manager.persist_stats(); |
| 14411 | } | ||
| 14412 | |||
| 14413 | timespec ts; | ||
| 14414 | 183447 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 14415 | |||
| 14416 | // Flush the WAL. Sync it for both background and never modes to copy | ||
| 14417 | // InnoDB's behavior. For mode never, the wal file isn't even written, | ||
| 14418 | // whereas background writes to the wal file, but issues the syncs in a | ||
| 14419 | // background thread. | ||
| 14420 |
5/6✓ Branch 0 taken 183447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4877 times.
✓ Branch 3 taken 178570 times.
✓ Branch 4 taken 4877 times.
✓ Branch 5 taken 178570 times.
|
188324 | if (rdb && (rocksdb_flush_log_at_trx_commit != FLUSH_LOG_SYNC) && |
| 14421 |
1/2✓ Branch 0 taken 4877 times.
✗ Branch 1 not taken.
|
4877 | !rocksdb_db_options->allow_mmap_writes) { |
| 14422 |
1/2✓ Branch 0 taken 4877 times.
✗ Branch 1 not taken.
|
4877 | bool sync = rdb_sync_wal_supported(); |
| 14423 |
1/2✓ Branch 0 taken 4877 times.
✗ Branch 1 not taken.
|
4877 | const rocksdb::Status s = rdb->FlushWAL(sync); |
| 14424 |
2/4✓ Branch 0 taken 4877 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4877 times.
|
4877 | if (!s.ok()) { |
| 14425 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_BG_THREAD); | |
| 14426 | } | ||
| 14427 | 4877 | } | |
| 14428 | |||
| 14429 | // Recalculate statistics for indexes only if | ||
| 14430 | // rocksdb_table_stats_use_table_scan is disabled. | ||
| 14431 | // Otherwise, Rdb_index_stats_thread will do the work | ||
| 14432 |
3/4✓ Branch 0 taken 182737 times.
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 182737 times.
|
183447 | if (!rocksdb_table_stats_use_table_scan && rocksdb_stats_recalc_rate) { |
| 14433 | ✗ | std::vector<std::string> to_recalc; | |
| 14434 | ✗ | if (rdb_tables_to_recalc.empty()) { | |
| 14435 | struct Rdb_index_collector : public Rdb_tables_scanner { | ||
| 14436 | ✗ | int add_table(Rdb_tbl_def *tdef) override { | |
| 14437 | ✗ | rdb_tables_to_recalc.push_back(tdef->full_tablename()); | |
| 14438 | ✗ | return HA_EXIT_SUCCESS; | |
| 14439 | } | ||
| 14440 | ✗ | } collector; | |
| 14441 | ✗ | ddl_manager.scan_for_tables(&collector); | |
| 14442 | } | ||
| 14443 | |||
| 14444 | ✗ | while (to_recalc.size() < rocksdb_stats_recalc_rate && | |
| 14445 | ✗ | !rdb_tables_to_recalc.empty()) { | |
| 14446 | ✗ | to_recalc.push_back(rdb_tables_to_recalc.back()); | |
| 14447 | ✗ | rdb_tables_to_recalc.pop_back(); | |
| 14448 | } | ||
| 14449 | |||
| 14450 | ✗ | for (const auto &tbl_name : to_recalc) { | |
| 14451 | ✗ | calculate_stats_for_table(tbl_name, SCAN_TYPE_NONE); | |
| 14452 | } | ||
| 14453 | } | ||
| 14454 | |||
| 14455 | // Set the next timestamp for mysql_cond_timedwait() (which ends up calling | ||
| 14456 | // pthread_cond_timedwait()) to wait on. | ||
| 14457 | 183447 | ts_next_sync.tv_sec = ts.tv_sec + WAKE_UP_INTERVAL; | |
| 14458 | 183447 | } | |
| 14459 | |||
| 14460 | // save remaining stats which might've left unsaved | ||
| 14461 |
1/2✓ Branch 0 taken 866 times.
✗ Branch 1 not taken.
|
866 | ddl_manager.persist_stats(); |
| 14462 | 866 | } | |
| 14463 | |||
| 14464 | 902 | void Rdb_index_stats_thread::run() { | |
| 14465 | 902 | const int WAKE_UP_INTERVAL = 1; | |
| 14466 | #ifdef TARGET_OS_LINUX | ||
| 14467 | 902 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); | |
| 14468 | 902 | m_tid_set = true; | |
| 14469 | 902 | m_tid = syscall(SYS_gettid); | |
| 14470 | 902 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14471 | #endif | ||
| 14472 | |||
| 14473 | 902 | renice(rocksdb_table_stats_background_thread_nice_value); | |
| 14474 | for (;;) { | ||
| 14475 |
2/4✓ Branch 0 taken 1621 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1621 times.
✗ Branch 3 not taken.
|
1621 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 14476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1621 times.
|
1621 | if (m_killed) { |
| 14477 | ✗ | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); | |
| 14478 | ✗ | break; | |
| 14479 | } | ||
| 14480 | |||
| 14481 | timespec ts; | ||
| 14482 | 1621 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 14483 | |||
| 14484 | // Wait for 24 hours if the table scan based index calculation | ||
| 14485 | // is off. When the switch is turned on and any request is added | ||
| 14486 | // to the recalc queue, this thread will be signaled. | ||
| 14487 | 3242 | ts.tv_sec += | |
| 14488 |
2/2✓ Branch 0 taken 728 times.
✓ Branch 1 taken 893 times.
|
1621 | (rocksdb_table_stats_use_table_scan) ? WAKE_UP_INTERVAL : 24 * 60 * 60; |
| 14489 | |||
| 14490 | const auto ret MY_ATTRIBUTE((__unused__)) = | ||
| 14491 |
1/2✓ Branch 0 taken 1585 times.
✗ Branch 1 not taken.
|
1621 | mysql_cond_timedwait(&m_signal_cond, &m_signal_mutex, &ts); |
| 14492 | |||
| 14493 |
2/2✓ Branch 0 taken 866 times.
✓ Branch 1 taken 719 times.
|
1585 | if (m_killed) { |
| 14494 |
2/4✓ Branch 0 taken 866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 866 times.
✗ Branch 3 not taken.
|
866 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 14495 | 866 | break; | |
| 14496 | } | ||
| 14497 | |||
| 14498 | // Make sure, no program error is returned | ||
| 14499 |
3/4✓ Branch 0 taken 685 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 685 times.
|
719 | assert(ret == 0 || ret == ETIMEDOUT); |
| 14500 |
2/4✓ Branch 0 taken 719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 719 times.
✗ Branch 3 not taken.
|
719 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 14501 | |||
| 14502 | for (;;) { | ||
| 14503 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
|
760 | if (!rocksdb_table_stats_use_table_scan) { |
| 14504 | // Clear the recalc queue | ||
| 14505 | ✗ | clear_all_index_stats_requests(); | |
| 14506 | ✗ | break; | |
| 14507 | } | ||
| 14508 | |||
| 14509 | 760 | std::string tbl_name; | |
| 14510 |
3/4✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 645 times.
✓ Branch 3 taken 115 times.
|
760 | if (!get_index_stats_request(&tbl_name)) { |
| 14511 | // No request in the recalc queue | ||
| 14512 | 645 | break; | |
| 14513 | } | ||
| 14514 | |||
| 14515 | 115 | Rdb_table_stats tbl_stats; | |
| 14516 |
3/4✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 111 times.
|
115 | if (ddl_manager.find_table_stats(tbl_name, &tbl_stats) != |
| 14517 | HA_EXIT_SUCCESS) { | ||
| 14518 | // The table has been dropped. Skip this table. | ||
| 14519 | 4 | continue; | |
| 14520 | } | ||
| 14521 | |||
| 14522 | 111 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 14523 |
2/2✓ Branch 0 taken 74 times.
✓ Branch 1 taken 37 times.
|
111 | if (difftime(ts.tv_sec, tbl_stats.m_last_recalc) < |
| 14524 | RDB_MIN_RECALC_INTERVAL) { | ||
| 14525 | /* Stats were (re)calculated not long ago. To avoid | ||
| 14526 | too frequent stats updates we put back the table on | ||
| 14527 | the recalc queue and do nothing. */ | ||
| 14528 | |||
| 14529 |
1/2✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
|
74 | add_index_stats_request(tbl_name); |
| 14530 | 74 | break; | |
| 14531 | } | ||
| 14532 | |||
| 14533 |
11/20✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 31 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 6 times.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✗ Branch 19 not taken.
|
37 | DBUG_EXECUTE_IF("rocksdb_is_bg_thread", { |
| 14534 | if (tbl_name == "test.t") { | ||
| 14535 | THD *thd = new THD(); | ||
| 14536 | thd->thread_stack = reinterpret_cast<char *>(&thd); | ||
| 14537 | thd->store_globals(); | ||
| 14538 | |||
| 14539 | static constexpr char act[] = | ||
| 14540 | "now wait_for ready_to_calculate_index_stats"; | ||
| 14541 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 14542 | |||
| 14543 | thd->restore_globals(); | ||
| 14544 | delete thd; | ||
| 14545 | } | ||
| 14546 | }); | ||
| 14547 | |||
| 14548 | int err = | ||
| 14549 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | calculate_stats_for_table(tbl_name, SCAN_TYPE_FULL_TABLE, &m_killed); |
| 14550 | |||
| 14551 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if (err != HA_EXIT_SUCCESS) { |
| 14552 | ✗ | global_stats.table_index_stats_result[TABLE_INDEX_STATS_FAILURE].inc(); | |
| 14553 | ✗ | break; | |
| 14554 | } | ||
| 14555 | |||
| 14556 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | global_stats.table_index_stats_result[TABLE_INDEX_STATS_SUCCESS].inc(); |
| 14557 | |||
| 14558 |
11/20✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 31 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 6 times.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✗ Branch 19 not taken.
|
37 | DBUG_EXECUTE_IF("rocksdb_is_bg_thread", { |
| 14559 | if (tbl_name == "test.t") { | ||
| 14560 | THD *thd = new THD(); | ||
| 14561 | thd->thread_stack = reinterpret_cast<char *>(&thd); | ||
| 14562 | thd->store_globals(); | ||
| 14563 | |||
| 14564 | static constexpr char act[] = | ||
| 14565 | "now signal index_stats_calculation_done"; | ||
| 14566 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 14567 | |||
| 14568 | thd->restore_globals(); | ||
| 14569 | delete thd; | ||
| 14570 | } | ||
| 14571 | }); | ||
| 14572 |
3/3✓ Branch 0 taken 37 times.
✓ Branch 1 taken 719 times.
✓ Branch 2 taken 4 times.
|
801 | } |
| 14573 | 719 | } | |
| 14574 | |||
| 14575 | 866 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); | |
| 14576 | 866 | m_tid_set = false; | |
| 14577 | 866 | m_tid = 0; | |
| 14578 | 866 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14579 | 866 | } | |
| 14580 | |||
| 14581 | 760 | bool Rdb_index_stats_thread::get_index_stats_request(std::string *tbl_name) { | |
| 14582 | 760 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); | |
| 14583 |
2/2✓ Branch 0 taken 645 times.
✓ Branch 1 taken 115 times.
|
760 | if (m_requests.empty()) { |
| 14584 | 645 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14585 | 645 | return false; | |
| 14586 | } | ||
| 14587 | |||
| 14588 | 115 | *tbl_name = m_requests[0]; | |
| 14589 | 115 | m_requests.pop_front(); | |
| 14590 | |||
| 14591 | 115 | auto count = m_tbl_names.erase(*tbl_name); | |
| 14592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
|
115 | if (count != 1) { |
| 14593 | ✗ | assert(0); | |
| 14594 | } | ||
| 14595 | |||
| 14596 | 115 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14597 | 115 | return true; | |
| 14598 | } | ||
| 14599 | |||
| 14600 | 154 | void Rdb_index_stats_thread::add_index_stats_request( | |
| 14601 | const std::string &tbl_name) { | ||
| 14602 |
2/4✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
|
154 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); |
| 14603 | |||
| 14604 | /* Quit if already in the queue */ | ||
| 14605 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | auto ret = m_tbl_names.insert(tbl_name); |
| 14606 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 115 times.
|
154 | if (!ret.second) { |
| 14607 |
2/4✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
|
39 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); |
| 14608 | 39 | return; | |
| 14609 | } | ||
| 14610 | |||
| 14611 |
1/2✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
|
115 | m_requests.push_back(*ret.first); |
| 14612 |
2/4✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 115 times.
✗ Branch 3 not taken.
|
115 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); |
| 14613 |
1/2✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
|
115 | signal(); |
| 14614 | } | ||
| 14615 | |||
| 14616 | 6 | void Rdb_index_stats_thread::clear_all_index_stats_requests() { | |
| 14617 | 6 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); | |
| 14618 | 6 | m_requests.clear(); | |
| 14619 | 6 | m_tbl_names.clear(); | |
| 14620 | 6 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14621 | 6 | } | |
| 14622 | |||
| 14623 | 904 | int Rdb_index_stats_thread::renice(int nice_val) { | |
| 14624 | 904 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); | |
| 14625 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 904 times.
|
904 | if (!m_tid_set) { |
| 14626 | ✗ | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14627 | ✗ | return HA_EXIT_FAILURE; | |
| 14628 | } | ||
| 14629 | |||
| 14630 | #ifdef TARGET_OS_LINUX | ||
| 14631 | 904 | int ret = setpriority(PRIO_PROCESS, m_tid, nice_val); | |
| 14632 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 904 times.
|
904 | if (ret != 0) { |
| 14633 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 14634 | "Set index stats thread priority failed due to %s", | ||
| 14635 | strerror(errno)); | ||
| 14636 | ✗ | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14637 | ✗ | return HA_EXIT_FAILURE; | |
| 14638 | } | ||
| 14639 | #endif | ||
| 14640 | |||
| 14641 | 904 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14642 | 904 | return HA_EXIT_SUCCESS; | |
| 14643 | } | ||
| 14644 | |||
| 14645 | 11912 | size_t Rdb_index_stats_thread::get_request_queue_size() { | |
| 14646 | 11912 | size_t len = 0; | |
| 14647 | 11912 | RDB_MUTEX_LOCK_CHECK(m_is_mutex); | |
| 14648 | 11912 | len = m_requests.size(); | |
| 14649 | 11912 | RDB_MUTEX_UNLOCK_CHECK(m_is_mutex); | |
| 14650 | |||
| 14651 | 11912 | return len; | |
| 14652 | } | ||
| 14653 | |||
| 14654 | /* | ||
| 14655 | A background thread to handle manual compactions, | ||
| 14656 | except for dropping indexes/tables. Every second, it checks | ||
| 14657 | pending manual compactions, and it calls CompactRange if there is. | ||
| 14658 | */ | ||
| 14659 | 902 | void Rdb_manual_compaction_thread::run() { | |
| 14660 | 902 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); | |
| 14661 | for (;;) { | ||
| 14662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 183899 times.
|
183899 | if (m_killed) { |
| 14663 | ✗ | break; | |
| 14664 | } | ||
| 14665 | timespec ts; | ||
| 14666 | 183899 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 14667 | 183899 | ts.tv_sec += 1; | |
| 14668 | |||
| 14669 | const auto ret MY_ATTRIBUTE((__unused__)) = | ||
| 14670 |
1/2✓ Branch 0 taken 183863 times.
✗ Branch 1 not taken.
|
183899 | mysql_cond_timedwait(&m_signal_cond, &m_signal_mutex, &ts); |
| 14671 |
2/2✓ Branch 0 taken 866 times.
✓ Branch 1 taken 182997 times.
|
183863 | if (m_killed) { |
| 14672 | 866 | break; | |
| 14673 | } | ||
| 14674 | // make sure, no program error is returned | ||
| 14675 |
2/4✓ Branch 0 taken 182997 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 182997 times.
|
182997 | assert(ret == 0 || ret == ETIMEDOUT); |
| 14676 |
2/4✓ Branch 0 taken 182997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182997 times.
✗ Branch 3 not taken.
|
182997 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 14677 | |||
| 14678 |
2/4✓ Branch 0 taken 182997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182997 times.
✗ Branch 3 not taken.
|
182997 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); |
| 14679 | // Grab the first PENDING state item and proceed, if not empty. | ||
| 14680 |
2/2✓ Branch 0 taken 181552 times.
✓ Branch 1 taken 1445 times.
|
182997 | if (m_requests.empty()) { |
| 14681 |
2/4✓ Branch 0 taken 181552 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181552 times.
✗ Branch 3 not taken.
|
181552 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14682 |
2/4✓ Branch 0 taken 181552 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 181552 times.
✗ Branch 3 not taken.
|
181552 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 14683 | 181799 | continue; | |
| 14684 | } | ||
| 14685 | 1445 | auto it = m_requests.begin(); | |
| 14686 | 1445 | auto pending_it = m_requests.end(); | |
| 14687 | // Remove all items with client_done. client_done means | ||
| 14688 | // caller no longer uses the mcr object so it is safe to erase. | ||
| 14689 | // Pick first PENDING state item | ||
| 14690 | 1445 | it = m_requests.begin(); | |
| 14691 |
2/2✓ Branch 0 taken 2411 times.
✓ Branch 1 taken 1445 times.
|
3856 | while (it != m_requests.end()) { |
| 14692 |
2/2✓ Branch 0 taken 1207 times.
✓ Branch 1 taken 1204 times.
|
2411 | if (it->second.client_done) { |
| 14693 | // If state is PENDING, decrement counter | ||
| 14694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1207 times.
|
1207 | if (it->second.state == Manual_compaction_request::PENDING) { |
| 14695 | ✗ | rocksdb_manual_compactions_pending--; | |
| 14696 | } | ||
| 14697 |
1/2✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
|
1207 | m_requests.erase(it++); |
| 14698 |
3/4✓ Branch 0 taken 1204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1198 times.
✓ Branch 3 taken 6 times.
|
2408 | } else if (it->second.state == Manual_compaction_request::PENDING && |
| 14699 |
2/2✓ Branch 0 taken 1198 times.
✓ Branch 1 taken 6 times.
|
2408 | pending_it == m_requests.end()) { |
| 14700 | // found | ||
| 14701 | 1198 | pending_it = it; | |
| 14702 | 1198 | it++; | |
| 14703 | } else { | ||
| 14704 | 6 | it++; | |
| 14705 | } | ||
| 14706 | } | ||
| 14707 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 1198 times.
|
1445 | if (pending_it == m_requests.end()) { |
| 14708 |
2/4✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 247 times.
✗ Branch 3 not taken.
|
247 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14709 |
2/4✓ Branch 0 taken 247 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 247 times.
✗ Branch 3 not taken.
|
247 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 14710 | 247 | continue; | |
| 14711 | } | ||
| 14712 | |||
| 14713 | 1198 | Manual_compaction_request &mcr = pending_it->second; | |
| 14714 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1198 times.
|
1198 | assert(mcr.cf); |
| 14715 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1198 times.
|
1198 | assert(mcr.state == Manual_compaction_request::PENDING); |
| 14716 | 1198 | mcr.state = Manual_compaction_request::RUNNING; | |
| 14717 | 1198 | rocksdb_manual_compactions_running++; | |
| 14718 | 1198 | rocksdb_manual_compactions_pending--; | |
| 14719 |
2/4✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1198 times.
✗ Branch 3 not taken.
|
1198 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14720 | |||
| 14721 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1198 times.
|
1198 | assert(mcr.state == Manual_compaction_request::RUNNING); |
| 14722 | // NO_LINT_DEBUG | ||
| 14723 |
10/20✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1198 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1198 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1198 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1198 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1198 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1198 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1198 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1198 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1198 times.
✗ Branch 19 not taken.
|
1198 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 14724 | "Manual Compaction id %d cf %s started.", mcr.mc_id, | ||
| 14725 | mcr.cf->GetName().c_str()); | ||
| 14726 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1189 times.
|
1198 | if (rocksdb_debug_manual_compaction_delay > 0) { |
| 14727 | // In Facebook MySQL 5.6.35, my_sleep breaks the sleep when the server | ||
| 14728 | // gets a shutdown signal and this code depended on that behavior. | ||
| 14729 | // In 5.7, for whatever reason, this is not the case. my_sleep will | ||
| 14730 | // continue to sleep until the sleep time has elapsed. For the purpose | ||
| 14731 | // of this variable and the accompanying test case, we need to break this | ||
| 14732 | // down into a loop that sleeps and checks to see if the thread was | ||
| 14733 | // signalled with the stop flag. It is ugly, but without having DBUG_SYNC | ||
| 14734 | // available in background threads, it is good enough for the test. | ||
| 14735 |
2/2✓ Branch 0 taken 243 times.
✓ Branch 1 taken 9 times.
|
252 | for (uint32_t sleeps = 0; sleeps < rocksdb_debug_manual_compaction_delay; |
| 14736 | sleeps++) { | ||
| 14737 |
2/4✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✗ Branch 3 not taken.
|
243 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 14738 | 243 | const bool local_stop = m_killed; | |
| 14739 |
2/4✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✗ Branch 3 not taken.
|
243 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); |
| 14740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 243 times.
|
243 | if (local_stop) break; |
| 14741 |
1/2✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
|
243 | my_sleep(1000000); |
| 14742 | } | ||
| 14743 | } | ||
| 14744 | |||
| 14745 |
10/18✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1195 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
1198 | DBUG_EXECUTE_IF("rocksdb_manual_compaction", { |
| 14746 | THD *thd = new THD(); | ||
| 14747 | thd->thread_stack = reinterpret_cast<char *>(&(thd)); | ||
| 14748 | thd->store_globals(); | ||
| 14749 | static constexpr char act[] = | ||
| 14750 | "now signal ready_to_mark_cf_dropped_in_manual_compaction wait_for " | ||
| 14751 | "mark_cf_dropped_done_in_manual_compaction"; | ||
| 14752 | assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); | ||
| 14753 | thd->restore_globals(); | ||
| 14754 | delete thd; | ||
| 14755 | }); | ||
| 14756 | |||
| 14757 | // CompactRange may take a very long time. On clean shutdown, | ||
| 14758 | // it is cancelled by CancelAllBackgroundWork, then status is | ||
| 14759 | // set to shutdownInProgress. | ||
| 14760 | const rocksdb::Status s = | ||
| 14761 |
1/2✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
|
1198 | rdb->CompactRange(mcr.option, mcr.cf.get(), mcr.start, mcr.limit); |
| 14762 | |||
| 14763 | 1198 | rocksdb_manual_compactions_running--; | |
| 14764 |
3/4✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1186 times.
✓ Branch 3 taken 12 times.
|
1198 | if (s.ok()) { |
| 14765 | 1186 | rocksdb_manual_compactions_processed++; | |
| 14766 | // NO_LINT_DEBUG | ||
| 14767 |
10/20✓ Branch 0 taken 1186 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1186 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1186 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1186 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1186 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1186 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1186 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1186 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1186 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1186 times.
✗ Branch 19 not taken.
|
1186 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 14768 | "Manual Compaction id %d cf %s ended.", mcr.mc_id, | ||
| 14769 | mcr.cf->GetName().c_str()); | ||
| 14770 |
1/2✓ Branch 0 taken 1186 times.
✗ Branch 1 not taken.
|
1186 | set_state(&mcr, Manual_compaction_request::SUCCESS); |
| 14771 | } else { | ||
| 14772 |
4/6✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 9 times.
|
12 | if (!cf_manager.get_cf(mcr.cf->GetID())) { |
| 14773 | // NO_LINT_DEBUG | ||
| 14774 |
10/20✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
|
3 | LogPluginErrMsg(INFORMATION_LEVEL, 0, "cf %s has been dropped", |
| 14775 | mcr.cf->GetName().c_str()); | ||
| 14776 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | set_state(&mcr, Manual_compaction_request::SUCCESS); |
| 14777 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | } else if (s.IsIncomplete()) { |
| 14778 | // NO_LINT_DEBUG | ||
| 14779 |
13/26✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 9 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 9 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 9 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 9 times.
✗ Branch 25 not taken.
|
9 | LogPluginErrMsg(INFORMATION_LEVEL, 0, |
| 14780 | "Manual Compaction id %d cf %s cancelled. (%d:%d, %s)", | ||
| 14781 | mcr.mc_id, mcr.cf->GetName().c_str(), s.code(), | ||
| 14782 | s.subcode(), s.getState()); | ||
| 14783 | // Cancelled | ||
| 14784 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | set_state(&mcr, Manual_compaction_request::CANCEL); |
| 14785 | 9 | rocksdb_manual_compactions_cancelled++; | |
| 14786 | } else { | ||
| 14787 | // NO_LINT_DEBUG | ||
| 14788 | ✗ | LogPluginErrMsg(INFORMATION_LEVEL, 0, | |
| 14789 | "Manual Compaction id %d cf %s aborted. (%d:%d, %s)", | ||
| 14790 | mcr.mc_id, mcr.cf->GetName().c_str(), s.code(), | ||
| 14791 | s.subcode(), s.getState()); | ||
| 14792 | ✗ | set_state(&mcr, Manual_compaction_request::FAILURE); | |
| 14793 | ✗ | if (!s.IsShutdownInProgress()) { | |
| 14794 | ✗ | rdb_handle_io_error(s, RDB_IO_ERROR_BG_THREAD); | |
| 14795 | } else { | ||
| 14796 | ✗ | assert(m_requests.size() == 1); | |
| 14797 | } | ||
| 14798 | } | ||
| 14799 | } | ||
| 14800 |
2/4✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1198 times.
✗ Branch 3 not taken.
|
1198 | RDB_MUTEX_LOCK_CHECK(m_signal_mutex); |
| 14801 | 184195 | } | |
| 14802 | 866 | clear_all_manual_compaction_requests(); | |
| 14803 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 866 times.
|
866 | assert(m_requests.empty()); |
| 14804 | 866 | RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); | |
| 14805 | 866 | } | |
| 14806 | |||
| 14807 | 866 | void Rdb_manual_compaction_thread::clear_all_manual_compaction_requests() { | |
| 14808 | 866 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); | |
| 14809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 866 times.
|
866 | assert(rocksdb_manual_compactions_pending == 0); |
| 14810 | 866 | m_requests.clear(); | |
| 14811 | 866 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); | |
| 14812 | 866 | } | |
| 14813 | |||
| 14814 | 13 | void Rdb_manual_compaction_thread:: | |
| 14815 | cancel_all_pending_manual_compaction_requests() { | ||
| 14816 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
13 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); |
| 14817 | 13 | auto it = m_requests.begin(); | |
| 14818 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
|
19 | while (it != m_requests.end()) { |
| 14819 | 6 | Manual_compaction_request &mcr = it->second; | |
| 14820 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (mcr.state == Manual_compaction_request::PENDING) { |
| 14821 | 3 | mcr.state = Manual_compaction_request::CANCEL; | |
| 14822 | 3 | rocksdb_manual_compactions_cancelled++; | |
| 14823 | 3 | rocksdb_manual_compactions_pending--; | |
| 14824 | } | ||
| 14825 | 6 | it++; | |
| 14826 | } | ||
| 14827 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(rocksdb_manual_compactions_pending == 0); |
| 14828 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
13 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14829 | 13 | } | |
| 14830 | |||
| 14831 | /** | ||
| 14832 | * Requesting to cancel a Manual Compaction job with mc_id. | ||
| 14833 | * Only PENDING or RUNNING states need cancellation. | ||
| 14834 | * This function may take a while if state is RUNNING. | ||
| 14835 | * Returning true if hitting timeout and state is RUNNING. | ||
| 14836 | */ | ||
| 14837 | 12 | bool Rdb_manual_compaction_thread::cancel_manual_compaction_request( | |
| 14838 | const int mc_id, const int timeout_100ms) { | ||
| 14839 | 12 | Manual_compaction_request::mc_state state = | |
| 14840 | Manual_compaction_request::PENDING; | ||
| 14841 | |||
| 14842 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); |
| 14843 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | auto it = m_requests.find(mc_id); |
| 14844 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (it != m_requests.end()) { |
| 14845 | 12 | Manual_compaction_request &mcr = it->second; | |
| 14846 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (mcr.state == Manual_compaction_request::PENDING) { |
| 14847 | 6 | mcr.state = Manual_compaction_request::CANCEL; | |
| 14848 | 6 | rocksdb_manual_compactions_cancelled++; | |
| 14849 | 6 | rocksdb_manual_compactions_pending--; | |
| 14850 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14851 | 6 | return false; | |
| 14852 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | } else if (mcr.state == Manual_compaction_request::RUNNING) { |
| 14853 | // explicitly requesting to cancel compaction (cancellation happens in | ||
| 14854 | // background may take time) | ||
| 14855 | 6 | mcr.option.canceled->store(true, std::memory_order_release); | |
| 14856 | 6 | state = mcr.state; | |
| 14857 | } | ||
| 14858 | } | ||
| 14859 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14860 | |||
| 14861 | // Waiting to get manual compaction to get cancelled. | ||
| 14862 | // Even if returning timeouts to clients, manual compaction | ||
| 14863 | // is still running so further compactions can remain | ||
| 14864 | // in pending state until the compaction completes cancellation. | ||
| 14865 | 6 | uint64_t retry = timeout_100ms; | |
| 14866 |
4/4✓ Branch 0 taken 1811 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1808 times.
✓ Branch 3 taken 3 times.
|
1814 | while (retry > 0 && state == Manual_compaction_request::RUNNING) { |
| 14867 |
1/2✓ Branch 0 taken 1808 times.
✗ Branch 1 not taken.
|
1808 | my_sleep(100000); |
| 14868 | 1808 | retry--; | |
| 14869 |
1/2✓ Branch 0 taken 1808 times.
✗ Branch 1 not taken.
|
1808 | state = manual_compaction_state(mc_id); |
| 14870 | } | ||
| 14871 | |||
| 14872 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | return retry <= 0 && state == Manual_compaction_request::RUNNING; |
| 14873 | } | ||
| 14874 | |||
| 14875 | /** | ||
| 14876 | * This function is for clients to request for Manual Compaction. | ||
| 14877 | * This function adds mcr (Manual Compaction Request) in a queue | ||
| 14878 | * as PENDING state then returns. Worker Thread then later picks it up | ||
| 14879 | * and processes compaction. | ||
| 14880 | * Clients should call set_client_done() when the clients are done with | ||
| 14881 | * the status of the requests. | ||
| 14882 | */ | ||
| 14883 | 1213 | int Rdb_manual_compaction_thread::request_manual_compaction( | |
| 14884 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cf, rocksdb::Slice *start, | ||
| 14885 | rocksdb::Slice *limit, const uint manual_compaction_threads, | ||
| 14886 | const rocksdb::BottommostLevelCompaction bottommost_level_compaction) { | ||
| 14887 | 1213 | int mc_id = -1; | |
| 14888 |
2/4✓ Branch 0 taken 1213 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1213 times.
✗ Branch 3 not taken.
|
1213 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); |
| 14889 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1207 times.
|
1213 | if (m_requests.size() >= rocksdb_max_manual_compactions) { |
| 14890 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14891 | 6 | return mc_id; | |
| 14892 | } | ||
| 14893 | 1207 | Manual_compaction_request mcr; | |
| 14894 | 1207 | mc_id = mcr.mc_id = ++m_latest_mc_id; | |
| 14895 | 1207 | mcr.state = Manual_compaction_request::PENDING; | |
| 14896 | 1207 | mcr.cf = cf; | |
| 14897 | 1207 | mcr.start = start; | |
| 14898 | 1207 | mcr.limit = limit; | |
| 14899 | 1207 | mcr.option = getCompactRangeOptions(manual_compaction_threads, | |
| 14900 | bottommost_level_compaction); | ||
| 14901 | mcr.canceled = | ||
| 14902 |
2/4✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1207 times.
✗ Branch 3 not taken.
|
1207 | std::shared_ptr<std::atomic<bool>>(new std::atomic<bool>(false)); |
| 14903 | 1207 | mcr.option.canceled = mcr.canceled.get(); | |
| 14904 | 1207 | mcr.client_done = false; | |
| 14905 | 1207 | rocksdb_manual_compactions_pending++; | |
| 14906 |
2/4✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1207 times.
✗ Branch 3 not taken.
|
1207 | m_requests.insert(std::make_pair(mcr.mc_id, mcr)); |
| 14907 |
2/4✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1207 times.
✗ Branch 3 not taken.
|
1207 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14908 | 1207 | return mc_id; | |
| 14909 | 1207 | } | |
| 14910 | |||
| 14911 | Rdb_manual_compaction_thread::Manual_compaction_request::mc_state | ||
| 14912 | 14579 | Rdb_manual_compaction_thread::manual_compaction_state(const int mc_id) { | |
| 14913 | 14579 | Manual_compaction_request::mc_state state = | |
| 14914 | Manual_compaction_request::SUCCESS; | ||
| 14915 |
2/4✓ Branch 0 taken 14581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14581 times.
✗ Branch 3 not taken.
|
14579 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); |
| 14916 |
1/2✓ Branch 0 taken 14581 times.
✗ Branch 1 not taken.
|
14581 | auto it = m_requests.find(mc_id); |
| 14917 |
1/2✓ Branch 0 taken 14581 times.
✗ Branch 1 not taken.
|
14581 | if (it != m_requests.end()) { |
| 14918 | 14581 | state = it->second.state; | |
| 14919 | } | ||
| 14920 |
2/4✓ Branch 0 taken 14581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14581 times.
✗ Branch 3 not taken.
|
14581 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14921 | 14581 | return state; | |
| 14922 | } | ||
| 14923 | |||
| 14924 | 1198 | void Rdb_manual_compaction_thread::set_state( | |
| 14925 | Manual_compaction_request *mcr, | ||
| 14926 | const Manual_compaction_request::mc_state new_state) { | ||
| 14927 | 1198 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); | |
| 14928 | 1198 | mcr->state = new_state; | |
| 14929 | 1198 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); | |
| 14930 | 1198 | } | |
| 14931 | |||
| 14932 | 1207 | bool Rdb_manual_compaction_thread::set_client_done(const int mc_id) { | |
| 14933 | 1207 | bool rc = false; | |
| 14934 |
2/4✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1207 times.
✗ Branch 3 not taken.
|
1207 | RDB_MUTEX_LOCK_CHECK(m_mc_mutex); |
| 14935 |
1/2✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
|
1207 | auto it = m_requests.find(mc_id); |
| 14936 |
1/2✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
|
1207 | if (it != m_requests.end()) { |
| 14937 | 1207 | Manual_compaction_request &mcr = it->second; | |
| 14938 | 1207 | mcr.client_done = true; | |
| 14939 | 1207 | rc = true; | |
| 14940 | } | ||
| 14941 |
2/4✓ Branch 0 taken 1207 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1207 times.
✗ Branch 3 not taken.
|
1207 | RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); |
| 14942 | 1207 | return rc; | |
| 14943 | } | ||
| 14944 | |||
| 14945 | /** | ||
| 14946 | * Locking read + Not Found + Read Committed occurs if we accessed | ||
| 14947 | * a row by Seek, tried to lock it, failed, released and reacquired the | ||
| 14948 | * snapshot (because of READ COMMITTED mode) and the row was deleted by | ||
| 14949 | * someone else in the meantime. | ||
| 14950 | * If so, we either just skipping the row, or re-creating a snapshot | ||
| 14951 | * and seek again. In both cases, Read Committed constraint is not broken. | ||
| 14952 | */ | ||
| 14953 | 186340909 | bool ha_rocksdb::should_skip_invalidated_record(const int rc) const { | |
| 14954 |
6/6✓ Branch 0 taken 4067900 times.
✓ Branch 1 taken 182273009 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 4067822 times.
✓ Branch 4 taken 78 times.
✓ Branch 5 taken 186340831 times.
|
186340987 | if ((m_lock_rows != RDB_LOCK_NONE && rc == HA_ERR_KEY_NOT_FOUND && |
| 14955 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | my_core::thd_tx_isolation(ha_thd()) == ISO_READ_COMMITTED)) { |
| 14956 | 78 | return true; | |
| 14957 | } | ||
| 14958 | 186340831 | return false; | |
| 14959 | } | ||
| 14960 | |||
| 14961 | 614 | bool ha_rocksdb::should_skip_locked_record(const int rc) const { | |
| 14962 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 569 times.
|
614 | if (m_locked_row_action == THR_SKIP) { |
| 14963 | /* | ||
| 14964 | In the spirit of SKIP LOCKED, Deadlock and Busy are also skipped as the | ||
| 14965 | goal is to skip conflicting rows and only lock the rows that can be | ||
| 14966 | updated later | ||
| 14967 | */ | ||
| 14968 | if (rc == HA_ERR_LOCK_WAIT_TIMEOUT || rc == HA_ERR_LOCK_DEADLOCK || | ||
| 14969 | HA_ERR_ROCKSDB_STATUS_BUSY) { | ||
| 14970 | 45 | return true; | |
| 14971 | } | ||
| 14972 | } | ||
| 14973 | 569 | return false; | |
| 14974 | } | ||
| 14975 | |||
| 14976 | /** | ||
| 14977 | * Indicating snapshot needs to be re-created and retrying seek again, | ||
| 14978 | * instead of returning errors or empty set. This is normally applicable | ||
| 14979 | * when hitting kBusy when locking the first row of the transaction, | ||
| 14980 | * with Repeatable Read isolation level. | ||
| 14981 | */ | ||
| 14982 | 257396 | bool ha_rocksdb::should_recreate_snapshot(const int rc, | |
| 14983 | const bool is_new_snapshot) const { | ||
| 14984 |
5/6✓ Branch 0 taken 257396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 257375 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 257375 times.
|
257417 | if (should_skip_invalidated_record(rc) || |
| 14985 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | (rc == HA_ERR_ROCKSDB_STATUS_BUSY && is_new_snapshot)) { |
| 14986 | 21 | return true; | |
| 14987 | } | ||
| 14988 | 257375 | return false; | |
| 14989 | } | ||
| 14990 | |||
| 14991 | /** | ||
| 14992 | * If calling put/delete/singledelete without locking the row, | ||
| 14993 | * it is necessary to pass assume_tracked=false to RocksDB TX API. | ||
| 14994 | * Read Free Replication and Blind Deletes are the cases when | ||
| 14995 | * using TX API and skipping row locking. | ||
| 14996 | */ | ||
| 14997 | 7783884 | bool ha_rocksdb::can_assume_tracked(THD *thd) { | |
| 14998 |
5/6✓ Branch 0 taken 7898824 times.
✓ Branch 1 taken 2519 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7899509 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 7899509 times.
|
7783884 | if (use_read_free_rpl() || (THDVAR(thd, blind_delete_primary_key))) { |
| 14999 | 3 | return false; | |
| 15000 | } | ||
| 15001 | 7899509 | return true; | |
| 15002 | } | ||
| 15003 | |||
| 15004 | 282933 | bool ha_rocksdb::check_bloom_and_set_bounds( | |
| 15005 | THD *thd, const Rdb_key_def &kd, const rocksdb::Slice &eq_cond, | ||
| 15006 | size_t bound_len, uchar *const lower_bound, uchar *const upper_bound, | ||
| 15007 | rocksdb::Slice *lower_bound_slice, rocksdb::Slice *upper_bound_slice) { | ||
| 15008 | 282933 | bool can_use_bloom = can_use_bloom_filter(thd, kd, eq_cond); | |
| 15009 |
6/6✓ Branch 0 taken 218901 times.
✓ Branch 1 taken 64032 times.
✓ Branch 2 taken 218892 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 218892 times.
✓ Branch 5 taken 64041 times.
|
282933 | if (!can_use_bloom && (THDVAR(thd, enable_iterate_bounds))) { |
| 15010 | 218892 | setup_iterator_bounds(kd, eq_cond, bound_len, lower_bound, upper_bound, | |
| 15011 | lower_bound_slice, upper_bound_slice); | ||
| 15012 | } | ||
| 15013 | 282933 | return can_use_bloom; | |
| 15014 | } | ||
| 15015 | |||
| 15016 | /** | ||
| 15017 | Deciding if it is possible to use bloom filter or not. | ||
| 15018 | |||
| 15019 | @detail | ||
| 15020 | Even if bloom filter exists, it is not always possible | ||
| 15021 | to use bloom filter. If using bloom filter when you shouldn't, | ||
| 15022 | false negative may happen -- fewer rows than expected may be returned. | ||
| 15023 | It is users' responsibility to use bloom filter correctly. | ||
| 15024 | |||
| 15025 | If bloom filter does not exist, return value does not matter because | ||
| 15026 | RocksDB does not use bloom filter internally. | ||
| 15027 | |||
| 15028 | @param kd | ||
| 15029 | @param eq_cond Equal condition part of the key. This always includes | ||
| 15030 | system index id (4 bytes). | ||
| 15031 | */ | ||
| 15032 | 282933 | bool ha_rocksdb::can_use_bloom_filter(THD *thd, const Rdb_key_def &kd, | |
| 15033 | const rocksdb::Slice &eq_cond) { | ||
| 15034 | 282933 | bool can_use = false; | |
| 15035 | |||
| 15036 |
2/2✓ Branch 0 taken 60606 times.
✓ Branch 1 taken 222327 times.
|
282933 | if (THDVAR(thd, skip_bloom_filter_on_read)) { |
| 15037 | 60606 | return can_use; | |
| 15038 | } | ||
| 15039 | |||
| 15040 | 222327 | const rocksdb::SliceTransform *prefix_extractor = kd.get_extractor(); | |
| 15041 |
2/2✓ Branch 0 taken 70215 times.
✓ Branch 1 taken 152112 times.
|
222327 | if (prefix_extractor) { |
| 15042 | /* | ||
| 15043 | This is an optimized use case for CappedPrefixTransform. | ||
| 15044 | If eq_cond length >= prefix extractor length and if | ||
| 15045 | all keys are used for equal lookup, it is | ||
| 15046 | always possible to use bloom filter. | ||
| 15047 | |||
| 15048 | Prefix bloom filter can't be used on descending scan with | ||
| 15049 | prefix lookup (i.e. WHERE id1=1 ORDER BY id2 DESC), because of | ||
| 15050 | RocksDB's limitation. On ascending (or not sorting) scan, | ||
| 15051 | keys longer than the capped prefix length will be truncated down | ||
| 15052 | to the capped length and the resulting key is added to the bloom filter. | ||
| 15053 | |||
| 15054 | Keys shorter than the capped prefix length will be added to | ||
| 15055 | the bloom filter. When keys are looked up, key conditionals | ||
| 15056 | longer than the capped length can be used; key conditionals | ||
| 15057 | shorter require all parts of the key to be available | ||
| 15058 | for the short key match. | ||
| 15059 | */ | ||
| 15060 |
2/2✓ Branch 0 taken 64032 times.
✓ Branch 1 taken 6183 times.
|
70215 | if (prefix_extractor->SameResultWhenAppended(eq_cond)) { |
| 15061 | 64032 | can_use = true; | |
| 15062 | } else { | ||
| 15063 | 6183 | can_use = false; | |
| 15064 | } | ||
| 15065 | } | ||
| 15066 | |||
| 15067 | 222327 | return can_use; | |
| 15068 | } | ||
| 15069 | |||
| 15070 | /* For modules that need access to the global data structures */ | ||
| 15071 | 32821 | rocksdb::TransactionDB *rdb_get_rocksdb_db() { return rdb; } | |
| 15072 | |||
| 15073 | 4064 | Rdb_cf_manager &rdb_get_cf_manager() { return cf_manager; } | |
| 15074 | |||
| 15075 | 31 | const rocksdb::BlockBasedTableOptions &rdb_get_table_options() { | |
| 15076 | 31 | return *rocksdb_tbl_options; | |
| 15077 | } | ||
| 15078 | |||
| 15079 | 39038 | bool rdb_is_table_scan_index_stats_calculation_enabled() { | |
| 15080 | 39038 | return rocksdb_table_stats_use_table_scan; | |
| 15081 | } | ||
| 15082 | 59325 | bool rdb_is_ttl_enabled() { return rocksdb_enable_ttl; } | |
| 15083 | 3987 | bool rdb_is_ttl_read_filtering_enabled() { | |
| 15084 | 3987 | return rocksdb_enable_ttl_read_filtering; | |
| 15085 | } | ||
| 15086 | #if !defined(NDEBUG) | ||
| 15087 | 2298 | int rdb_dbug_set_ttl_rec_ts() { return rocksdb_debug_ttl_rec_ts; } | |
| 15088 | 1005 | int rdb_dbug_set_ttl_snapshot_ts() { return rocksdb_debug_ttl_snapshot_ts; } | |
| 15089 | 1281 | int rdb_dbug_set_ttl_read_filter_ts() { | |
| 15090 | 1281 | return rocksdb_debug_ttl_read_filter_ts; | |
| 15091 | } | ||
| 15092 | 56429 | bool rdb_dbug_set_ttl_ignore_pk() { return rocksdb_debug_ttl_ignore_pk; } | |
| 15093 | #endif // !defined(NDEBUG) | ||
| 15094 | |||
| 15095 | 16069 | void rdb_update_global_stats(const operation_type &type, uint count, | |
| 15096 | Rdb_tbl_def *td) { | ||
| 15097 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16069 times.
|
16069 | assert(type < ROWS_MAX); |
| 15098 | |||
| 15099 |
2/2✓ Branch 0 taken 14545 times.
✓ Branch 1 taken 1524 times.
|
16069 | if (count == 0) { |
| 15100 | 14545 | return; | |
| 15101 | } | ||
| 15102 | |||
| 15103 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1524 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1524 | if (td && td->m_is_mysql_system_table) { |
| 15104 | ✗ | global_stats.system_rows[type].add(count); | |
| 15105 | } else { | ||
| 15106 | 1524 | global_stats.rows[type].add(count); | |
| 15107 | } | ||
| 15108 | } | ||
| 15109 | |||
| 15110 | 54 | int rdb_get_table_perf_counters(const char *const tablename, | |
| 15111 | Rdb_perf_counters *const counters) { | ||
| 15112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | assert(counters != nullptr); |
| 15113 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | assert(tablename != nullptr); |
| 15114 | |||
| 15115 | Rdb_table_handler *table_handler; | ||
| 15116 | 54 | table_handler = rdb_open_tables.get_table_handler(tablename); | |
| 15117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (table_handler == nullptr) { |
| 15118 | ✗ | return HA_ERR_ROCKSDB_INVALID_TABLE; | |
| 15119 | } | ||
| 15120 | |||
| 15121 | 54 | counters->load(table_handler->m_table_perf_context); | |
| 15122 | |||
| 15123 | 54 | rdb_open_tables.release_table_handler(table_handler); | |
| 15124 | 54 | return HA_EXIT_SUCCESS; | |
| 15125 | } | ||
| 15126 | |||
| 15127 | ✗ | const char *get_rdb_io_error_string(const RDB_IO_ERROR_TYPE err_type) { | |
| 15128 | // If this assertion fails then this means that a member has been either added | ||
| 15129 | // to or removed from RDB_IO_ERROR_TYPE enum and this function needs to be | ||
| 15130 | // changed to return the appropriate value. | ||
| 15131 | static_assert(RDB_IO_ERROR_LAST == 4, "Please handle all the error types."); | ||
| 15132 | |||
| 15133 | ✗ | switch (err_type) { | |
| 15134 | ✗ | case RDB_IO_ERROR_TYPE::RDB_IO_ERROR_TX_COMMIT: | |
| 15135 | ✗ | return "RDB_IO_ERROR_TX_COMMIT"; | |
| 15136 | ✗ | case RDB_IO_ERROR_TYPE::RDB_IO_ERROR_DICT_COMMIT: | |
| 15137 | ✗ | return "RDB_IO_ERROR_DICT_COMMIT"; | |
| 15138 | ✗ | case RDB_IO_ERROR_TYPE::RDB_IO_ERROR_BG_THREAD: | |
| 15139 | ✗ | return "RDB_IO_ERROR_BG_THREAD"; | |
| 15140 | ✗ | case RDB_IO_ERROR_TYPE::RDB_IO_ERROR_GENERAL: | |
| 15141 | ✗ | return "RDB_IO_ERROR_GENERAL"; | |
| 15142 | ✗ | default: | |
| 15143 | ✗ | assert(false); | |
| 15144 | return "(unknown)"; | ||
| 15145 | } | ||
| 15146 | } | ||
| 15147 | |||
| 15148 | // In case of core dump generation we want this function NOT to be optimized | ||
| 15149 | // so that we can capture as much data as possible to debug the root cause | ||
| 15150 | // more efficiently. | ||
| 15151 | #if defined(NDEBUG) | ||
| 15152 | #ifdef __clang__ | ||
| 15153 | MY_ATTRIBUTE((optnone)) | ||
| 15154 | #else | ||
| 15155 | MY_ATTRIBUTE((optimize("O0"))) | ||
| 15156 | #endif | ||
| 15157 | #endif | ||
| 15158 | ✗ | void rdb_handle_io_error(const rocksdb::Status status, | |
| 15159 | const RDB_IO_ERROR_TYPE err_type) { | ||
| 15160 | ✗ | if (status.IsIOError()) { | |
| 15161 | ✗ | switch (err_type) { | |
| 15162 | ✗ | case RDB_IO_ERROR_TX_COMMIT: | |
| 15163 | case RDB_IO_ERROR_DICT_COMMIT: { | ||
| 15164 | ✗ | rdb_log_status_error(status, "failed to write to WAL"); | |
| 15165 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "aborting on WAL write error."); | |
| 15166 | ✗ | abort(); | |
| 15167 | break; | ||
| 15168 | } | ||
| 15169 | ✗ | case RDB_IO_ERROR_BG_THREAD: { | |
| 15170 | ✗ | rdb_log_status_error(status, "BG thread failed to write to RocksDB"); | |
| 15171 | /* NO_LINT_DEBUG */ | ||
| 15172 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "aborting on BG write error."); | |
| 15173 | ✗ | abort(); | |
| 15174 | break; | ||
| 15175 | } | ||
| 15176 | ✗ | case RDB_IO_ERROR_GENERAL: { | |
| 15177 | ✗ | rdb_log_status_error(status, "failed on I/O"); | |
| 15178 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "aborting on I/O error."); | |
| 15179 | ✗ | abort(); | |
| 15180 | break; | ||
| 15181 | } | ||
| 15182 | ✗ | default: | |
| 15183 | ✗ | assert(0); | |
| 15184 | break; | ||
| 15185 | } | ||
| 15186 | ✗ | } else if (status.IsCorruption()) { | |
| 15187 | ✗ | rdb_log_status_error(status, "data corruption detected!"); | |
| 15188 | ✗ | rdb_persist_corruption_marker(); | |
| 15189 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "aborting because of data corruption."); | |
| 15190 | ✗ | abort(); | |
| 15191 | ✗ | } else if (!status.ok()) { | |
| 15192 | ✗ | switch (err_type) { | |
| 15193 | ✗ | case RDB_IO_ERROR_TX_COMMIT: | |
| 15194 | case RDB_IO_ERROR_DICT_COMMIT: { | ||
| 15195 | ✗ | rdb_log_status_error(status, "Failed to write to WAL (non kIOError)"); | |
| 15196 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, "aborting on WAL write error."); | |
| 15197 | ✗ | abort(); | |
| 15198 | break; | ||
| 15199 | } | ||
| 15200 | ✗ | default: | |
| 15201 | ✗ | rdb_log_status_error(status, "Failed to read/write in RocksDB"); | |
| 15202 | ✗ | break; | |
| 15203 | } | ||
| 15204 | } | ||
| 15205 | } | ||
| 15206 | |||
| 15207 | 201034 | Rdb_dict_manager_selector *rdb_get_dict_manager(void) { return &dict_manager; } | |
| 15208 | |||
| 15209 | 22451 | Rdb_ddl_manager *rdb_get_ddl_manager(void) { return &ddl_manager; } | |
| 15210 | |||
| 15211 | 11390 | Rdb_hton_init_state *rdb_get_hton_init_state(void) { return &hton_init_state; } | |
| 15212 | |||
| 15213 | 1089 | void rocksdb_set_compaction_options( | |
| 15214 | my_core::THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 15215 | my_core::SYS_VAR *const var MY_ATTRIBUTE((__unused__)), void *const var_ptr, | ||
| 15216 | const void *const save) { | ||
| 15217 |
3/4✓ Branch 0 taken 163 times.
✓ Branch 1 taken 926 times.
✓ Branch 2 taken 163 times.
✗ Branch 3 not taken.
|
1089 | if (var_ptr && save) { |
| 15218 | 163 | *(uint64_t *)var_ptr = *(const uint64_t *)save; | |
| 15219 | } | ||
| 15220 | const Rdb_compact_params params = { | ||
| 15221 | 1089 | (uint64_t)rocksdb_compaction_sequential_deletes, | |
| 15222 | 1089 | (uint64_t)rocksdb_compaction_sequential_deletes_window, | |
| 15223 | 1089 | (uint64_t)rocksdb_compaction_sequential_deletes_file_size}; | |
| 15224 |
1/2✓ Branch 0 taken 1089 times.
✗ Branch 1 not taken.
|
1089 | if (properties_collector_factory) { |
| 15225 | 1089 | properties_collector_factory->SetCompactionParams(params); | |
| 15226 | } | ||
| 15227 | 1089 | } | |
| 15228 | |||
| 15229 | 22 | void rocksdb_set_table_stats_sampling_pct( | |
| 15230 | my_core::THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 15231 | my_core::SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 15232 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 15233 | 22 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15234 | |||
| 15235 | 22 | const uint32_t new_val = *static_cast<const uint32_t *>(save); | |
| 15236 | |||
| 15237 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
|
22 | if (new_val != rocksdb_table_stats_sampling_pct) { |
| 15238 | 18 | rocksdb_table_stats_sampling_pct = new_val; | |
| 15239 | |||
| 15240 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (properties_collector_factory) { |
| 15241 | 18 | properties_collector_factory->SetTableStatsSamplingPct( | |
| 15242 | rocksdb_table_stats_sampling_pct); | ||
| 15243 | } | ||
| 15244 | } | ||
| 15245 | |||
| 15246 | 22 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15247 | 22 | } | |
| 15248 | |||
| 15249 | 22 | void rocksdb_update_table_stats_use_table_scan(THD *const /* thd */, | |
| 15250 | struct SYS_VAR *const /* var */, | ||
| 15251 | void *const var_ptr, | ||
| 15252 | const void *const save) { | ||
| 15253 | 22 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15254 | 22 | bool old_val = *static_cast<const bool *>(var_ptr); | |
| 15255 | 22 | bool new_val = *static_cast<const bool *>(save); | |
| 15256 | |||
| 15257 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 12 times.
|
22 | if (old_val == new_val) { |
| 15258 | 10 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15259 | 10 | return; | |
| 15260 | } | ||
| 15261 | |||
| 15262 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (new_val) { |
| 15263 | struct Rdb_table_collector : public Rdb_tables_scanner { | ||
| 15264 | 3 | int add_table(Rdb_tbl_def *tdef) override { | |
| 15265 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(tdef->m_key_count > 0); |
| 15266 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | tdef->m_tbl_stats.set(tdef->m_key_count > 0 |
| 15267 | 3 | ? tdef->m_key_descr_arr[0]->m_stats.m_rows | |
| 15268 | : 0, | ||
| 15269 | 0, 0); | ||
| 15270 | 3 | return HA_EXIT_SUCCESS; | |
| 15271 | } | ||
| 15272 | 6 | } collector; | |
| 15273 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ddl_manager.scan_for_tables(&collector); |
| 15274 | |||
| 15275 | // We do not add all tables to the index stats recalculation queue | ||
| 15276 | // to avoid index stats calculation workload spike. | ||
| 15277 | } else { | ||
| 15278 | 6 | rdb_is_thread.clear_all_index_stats_requests(); | |
| 15279 | } | ||
| 15280 | |||
| 15281 | 12 | *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 15282 | 12 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15283 | } | ||
| 15284 | |||
| 15285 | 2 | int rocksdb_index_stats_thread_renice(THD *const /* thd */, | |
| 15286 | struct SYS_VAR *const /* var */, | ||
| 15287 | void *const save, | ||
| 15288 | struct st_mysql_value *const value) { | ||
| 15289 | long long nice_val; | ||
| 15290 | /* value is NULL */ | ||
| 15291 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (value->val_int(value, &nice_val)) { |
| 15292 | ✗ | return HA_EXIT_FAILURE; | |
| 15293 | } | ||
| 15294 | |||
| 15295 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (rdb_is_thread.renice(nice_val) != HA_EXIT_SUCCESS) { |
| 15296 | ✗ | return HA_EXIT_FAILURE; | |
| 15297 | } | ||
| 15298 | |||
| 15299 | 2 | *static_cast<int32_t *>(save) = static_cast<int32_t>(nice_val); | |
| 15300 | 2 | return HA_EXIT_SUCCESS; | |
| 15301 | } | ||
| 15302 | |||
| 15303 | /* | ||
| 15304 | This function allows setting the rate limiter's bytes per second value | ||
| 15305 | but only if the rate limiter is turned on which has to be done at startup. | ||
| 15306 | If the rate is already 0 (turned off) or we are changing it to 0 (trying | ||
| 15307 | to turn it off) this function will push a warning to the client and do | ||
| 15308 | nothing. | ||
| 15309 | This is similar to the code in innodb_doublewrite_update (found in | ||
| 15310 | storage/innobase/handler/ha_innodb.cc). | ||
| 15311 | */ | ||
| 15312 | 14 | void rocksdb_set_rate_limiter_bytes_per_sec( | |
| 15313 | my_core::THD *const thd, | ||
| 15314 | my_core::SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 15315 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 15316 | 14 | const uint64_t new_val = *static_cast<const uint64_t *>(save); | |
| 15317 |
4/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
|
14 | if (new_val == 0 || rocksdb_rate_limiter_bytes_per_sec == 0) { |
| 15318 | /* | ||
| 15319 | If a rate_limiter was not enabled at startup we can't change it nor | ||
| 15320 | can we disable it if one was created at startup | ||
| 15321 | */ | ||
| 15322 | 8 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 15323 | "RocksDB: rocksdb_rate_limiter_bytes_per_sec cannot " | ||
| 15324 | "be dynamically changed to or from 0. Do a clean " | ||
| 15325 | "shutdown if you want to change it from or to 0."); | ||
| 15326 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | } else if (new_val != rocksdb_rate_limiter_bytes_per_sec) { |
| 15327 | /* Apply the new value to the rate limiter and store it locally */ | ||
| 15328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(rocksdb_rate_limiter != nullptr); |
| 15329 | 6 | rocksdb_rate_limiter_bytes_per_sec = new_val; | |
| 15330 | 6 | rocksdb_rate_limiter->SetBytesPerSecond(new_val); | |
| 15331 | } | ||
| 15332 | 14 | } | |
| 15333 | |||
| 15334 | 7 | void rocksdb_set_sst_mgr_rate_bytes_per_sec( | |
| 15335 | my_core::THD *const thd, | ||
| 15336 | my_core::SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 15337 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 15338 | 7 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15339 | |||
| 15340 | 7 | const uint64_t new_val = *static_cast<const uint64_t *>(save); | |
| 15341 | |||
| 15342 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (new_val != rocksdb_sst_mgr_rate_bytes_per_sec) { |
| 15343 | 4 | rocksdb_sst_mgr_rate_bytes_per_sec = new_val; | |
| 15344 | |||
| 15345 | 4 | rocksdb_db_options->sst_file_manager->SetDeleteRateBytesPerSecond( | |
| 15346 | rocksdb_sst_mgr_rate_bytes_per_sec); | ||
| 15347 | } | ||
| 15348 | |||
| 15349 | 7 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15350 | 7 | } | |
| 15351 | |||
| 15352 | 7 | void rocksdb_set_delayed_write_rate(THD *thd, struct SYS_VAR *var, | |
| 15353 | void *var_ptr, const void *save) { | ||
| 15354 | 7 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15355 | 7 | const uint64_t new_val = *static_cast<const uint64_t *>(save); | |
| 15356 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (rocksdb_delayed_write_rate != new_val) { |
| 15357 | 4 | rocksdb_delayed_write_rate = new_val; | |
| 15358 | rocksdb::Status s = | ||
| 15359 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
16 | rdb->SetDBOptions({{"delayed_write_rate", std::to_string(new_val)}}); |
| 15360 | |||
| 15361 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (!s.ok()) { |
| 15362 | ✗ | LogPluginErrMsg( | |
| 15363 | WARNING_LEVEL, 0, | ||
| 15364 | "failed to update delayed_write_rate. status code = %d, status = %s", | ||
| 15365 | s.code(), s.ToString().c_str()); | ||
| 15366 | } | ||
| 15367 | 4 | } | |
| 15368 | 7 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15369 | 7 | } | |
| 15370 | |||
| 15371 | 38 | void rocksdb_set_max_latest_deadlocks(THD *thd, struct SYS_VAR *var, | |
| 15372 | void *var_ptr, const void *save) { | ||
| 15373 | 38 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15374 | 38 | const uint32_t new_val = *static_cast<const uint32_t *>(save); | |
| 15375 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 1 times.
|
38 | if (rocksdb_max_latest_deadlocks != new_val) { |
| 15376 | 37 | rocksdb_max_latest_deadlocks = new_val; | |
| 15377 | 37 | rdb->SetDeadlockInfoBufferSize(rocksdb_max_latest_deadlocks); | |
| 15378 | } | ||
| 15379 | 38 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15380 | 38 | } | |
| 15381 | |||
| 15382 | 938 | void rdb_set_collation_exception_list(const char *const exception_list) { | |
| 15383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 938 times.
|
938 | assert(rdb_collation_exceptions != nullptr); |
| 15384 | |||
| 15385 |
3/6✓ Branch 0 taken 938 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 938 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 938 times.
|
938 | if (!rdb_collation_exceptions->set_patterns(exception_list, |
| 15386 | get_regex_flags())) { | ||
| 15387 | ✗ | warn_about_bad_patterns(rdb_collation_exceptions, | |
| 15388 | "strict_collation_exceptions"); | ||
| 15389 | } | ||
| 15390 | 938 | } | |
| 15391 | |||
| 15392 | 36 | void rocksdb_set_collation_exception_list(THD *const thd, | |
| 15393 | struct SYS_VAR *const var, | ||
| 15394 | void *const var_ptr, | ||
| 15395 | const void *const save) { | ||
| 15396 | 36 | const char *const val = *static_cast<const char *const *>(save); | |
| 15397 | |||
| 15398 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | rdb_set_collation_exception_list(val == nullptr ? "" : val); |
| 15399 | |||
| 15400 | 36 | *static_cast<const char **>(var_ptr) = val; | |
| 15401 | 36 | } | |
| 15402 | |||
| 15403 | 1524 | int mysql_value_to_bool(struct st_mysql_value *value, bool *return_value) { | |
| 15404 | 1524 | int new_value_type = value->value_type(value); | |
| 15405 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1486 times.
|
1524 | if (new_value_type == MYSQL_VALUE_TYPE_STRING) { |
| 15406 | char buf[16]; | ||
| 15407 | 38 | int len = sizeof(buf); | |
| 15408 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | const char *str = value->val_str(value, buf, &len); |
| 15409 |
5/8✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22 times.
✓ Branch 7 taken 16 times.
|
76 | if (str && (my_strcasecmp(system_charset_info, "true", str) == 0 || |
| 15410 |
3/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 16 times.
|
38 | my_strcasecmp(system_charset_info, "on", str) == 0)) { |
| 15411 | 22 | *return_value = true; | |
| 15412 |
5/8✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 9 times.
|
32 | } else if (str && (my_strcasecmp(system_charset_info, "false", str) == 0 || |
| 15413 |
3/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 9 times.
|
16 | my_strcasecmp(system_charset_info, "off", str) == 0)) { |
| 15414 | 7 | *return_value = false; | |
| 15415 | } else { | ||
| 15416 | 9 | return 1; | |
| 15417 | } | ||
| 15418 |
1/2✓ Branch 0 taken 1486 times.
✗ Branch 1 not taken.
|
1486 | } else if (new_value_type == MYSQL_VALUE_TYPE_INT) { |
| 15419 | long long intbuf; | ||
| 15420 |
1/2✓ Branch 0 taken 1486 times.
✗ Branch 1 not taken.
|
1486 | value->val_int(value, &intbuf); |
| 15421 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1486 times.
|
1486 | if (intbuf > 1) return 1; |
| 15422 | 1486 | *return_value = intbuf > 0; | |
| 15423 | } else { | ||
| 15424 | ✗ | return 1; | |
| 15425 | } | ||
| 15426 | |||
| 15427 | 1515 | return 0; | |
| 15428 | } | ||
| 15429 | |||
| 15430 | 64 | static int rocksdb_validate_flush_log_at_trx_commit( | |
| 15431 | THD *const thd, | ||
| 15432 | struct SYS_VAR *const var, /* in: pointer to system variable */ | ||
| 15433 | void *var_ptr, /* out: immediate result for update function */ | ||
| 15434 | struct st_mysql_value *const value /* in: incoming value */) { | ||
| 15435 | long long new_value; | ||
| 15436 | |||
| 15437 | /* value is NULL */ | ||
| 15438 |
2/4✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
|
64 | if (value->val_int(value, &new_value)) { |
| 15439 | ✗ | return 1; | |
| 15440 | } | ||
| 15441 | |||
| 15442 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 64 times.
|
64 | if (rocksdb_db_options->allow_mmap_writes && new_value != FLUSH_LOG_NEVER) { |
| 15443 | ✗ | return 1; | |
| 15444 | } | ||
| 15445 | |||
| 15446 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | bool write_disable_wal = THDVAR(thd, write_disable_wal); |
| 15447 |
4/4✓ Branch 0 taken 27 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 26 times.
|
64 | if (new_value == FLUSH_LOG_SYNC && write_disable_wal) { |
| 15448 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error( |
| 15449 | ER_GET_ERRMSG, MYF(0), HA_ERR_ROCKSDB_STATUS_INVALID_ARGUMENT, | ||
| 15450 | "rocksdb_flush_log_at_trx_commit = 1 and rocksdb_write_disable_wal = ON" | ||
| 15451 | " are not compatible", | ||
| 15452 | rocksdb_hton_name); | ||
| 15453 | 1 | return 1; | |
| 15454 | } | ||
| 15455 | |||
| 15456 | 63 | *static_cast<uint32_t *>(var_ptr) = static_cast<uint32_t>(new_value); | |
| 15457 | 63 | return HA_EXIT_SUCCESS; | |
| 15458 | } | ||
| 15459 | 124 | static int rocksdb_check_write_disable_wal( | |
| 15460 | THD *const thd, struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 15461 | struct st_mysql_value *value) { | ||
| 15462 | bool new_value; | ||
| 15463 |
3/4✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 123 times.
|
124 | if (mysql_value_to_bool(value, &new_value) != 0) { |
| 15464 | 1 | return 1; | |
| 15465 | } | ||
| 15466 | |||
| 15467 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 115 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
|
123 | if (rocksdb_flush_log_at_trx_commit == FLUSH_LOG_SYNC && new_value) { |
| 15468 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error( |
| 15469 | ER_GET_ERRMSG, MYF(0), HA_ERR_ROCKSDB_STATUS_INVALID_ARGUMENT, | ||
| 15470 | "rocksdb_flush_log_at_trx_commit = 1 and rocksdb_write_disable_wal = ON" | ||
| 15471 | " are not compatible", | ||
| 15472 | rocksdb_hton_name); | ||
| 15473 | 1 | return 1; | |
| 15474 | } | ||
| 15475 | |||
| 15476 | 122 | *static_cast<bool *>(save) = new_value; | |
| 15477 | |||
| 15478 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | THDVAR(thd, write_disable_wal_save) = false; |
| 15479 | 122 | return 0; | |
| 15480 | } | ||
| 15481 | |||
| 15482 | 268 | int rocksdb_check_bulk_load(THD *const thd, | |
| 15483 | struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), | ||
| 15484 | void *save, struct st_mysql_value *value) { | ||
| 15485 | bool new_value; | ||
| 15486 |
3/4✓ Branch 0 taken 268 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 264 times.
|
268 | if (mysql_value_to_bool(value, &new_value) != 0) { |
| 15487 | 4 | return 1; | |
| 15488 | } | ||
| 15489 | |||
| 15490 |
1/2✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
|
264 | Rdb_transaction *tx = get_tx_from_thd(thd); |
| 15491 |
2/2✓ Branch 0 taken 194 times.
✓ Branch 1 taken 70 times.
|
264 | if (tx != nullptr) { |
| 15492 | bool is_critical_error; | ||
| 15493 |
1/2✓ Branch 0 taken 194 times.
✗ Branch 1 not taken.
|
194 | const int rc = tx->finish_bulk_load(&is_critical_error); |
| 15494 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
|
194 | if (rc != 0 && is_critical_error) { |
| 15495 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 15496 | "Error %d finalizing last SST file while setting bulk " | ||
| 15497 | "loading variable", | ||
| 15498 | rc); | ||
| 15499 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | THDVAR(thd, bulk_load) = 0; |
| 15500 | 3 | return 1; | |
| 15501 | } | ||
| 15502 | } | ||
| 15503 | |||
| 15504 | 261 | *static_cast<bool *>(save) = new_value; | |
| 15505 | 261 | return 0; | |
| 15506 | } | ||
| 15507 | |||
| 15508 | 62 | int rocksdb_check_bulk_load_allow_unsorted( | |
| 15509 | THD *const thd, struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 15510 | struct st_mysql_value *value) { | ||
| 15511 | bool new_value; | ||
| 15512 |
3/4✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 58 times.
|
62 | if (mysql_value_to_bool(value, &new_value) != 0) { |
| 15513 | 4 | return 1; | |
| 15514 | } | ||
| 15515 | |||
| 15516 |
3/4✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 55 times.
|
58 | if (THDVAR(thd, bulk_load)) { |
| 15517 |
9/18✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
3 | LogPluginErrMsg(ERROR_LEVEL, 0, |
| 15518 | "Cannot change this setting while bulk load is enabled"); | ||
| 15519 | |||
| 15520 | 3 | return 1; | |
| 15521 | } | ||
| 15522 | |||
| 15523 | 55 | *static_cast<bool *>(save) = new_value; | |
| 15524 | 55 | return 0; | |
| 15525 | } | ||
| 15526 | |||
| 15527 | 11 | static void rocksdb_set_max_background_jobs(THD *thd, struct SYS_VAR *const var, | |
| 15528 | void *const var_ptr, | ||
| 15529 | const void *const save) { | ||
| 15530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | assert(save != nullptr); |
| 15531 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | assert(rocksdb_db_options != nullptr); |
| 15532 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | assert(rocksdb_db_options->env != nullptr); |
| 15533 | |||
| 15534 | 11 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15535 | |||
| 15536 | 11 | const int new_val = *static_cast<const int *>(save); | |
| 15537 | |||
| 15538 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
|
11 | if (rocksdb_db_options->max_background_jobs != new_val) { |
| 15539 | 10 | rocksdb_db_options->max_background_jobs = new_val; | |
| 15540 | rocksdb::Status s = | ||
| 15541 |
4/8✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
40 | rdb->SetDBOptions({{"max_background_jobs", std::to_string(new_val)}}); |
| 15542 | |||
| 15543 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (!s.ok()) { |
| 15544 | ✗ | LogPluginErrMsg(WARNING_LEVEL, 0, | |
| 15545 | "failed to update max_background_jobs. Status code = %d, " | ||
| 15546 | "status = %s.", | ||
| 15547 | s.code(), s.ToString().c_str()); | ||
| 15548 | } | ||
| 15549 | 10 | } | |
| 15550 | |||
| 15551 | 11 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15552 | 11 | } | |
| 15553 | |||
| 15554 | 5 | static void rocksdb_set_max_background_compactions(THD *thd, | |
| 15555 | struct SYS_VAR *const var, | ||
| 15556 | void *const var_ptr, | ||
| 15557 | const void *const save) { | ||
| 15558 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | assert(save != nullptr); |
| 15559 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | assert(rocksdb_db_options != nullptr); |
| 15560 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | assert(rocksdb_db_options->env != nullptr); |
| 15561 | |||
| 15562 | 5 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15563 | |||
| 15564 | 5 | const int new_val = *static_cast<const int *>(save); | |
| 15565 | |||
| 15566 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | if (rocksdb_db_options->max_background_compactions != new_val) { |
| 15567 | 4 | rocksdb_db_options->max_background_compactions = new_val; | |
| 15568 | 4 | rocksdb::Status s = rdb->SetDBOptions( | |
| 15569 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
12 | {{"max_background_compactions", std::to_string(new_val)}}); |
| 15570 | |||
| 15571 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (!s.ok()) { |
| 15572 | /* NO_LINT_DEBUG */ | ||
| 15573 | ✗ | LogPluginErrMsg(WARNING_LEVEL, 0, | |
| 15574 | "MyRocks: failed to update max_background_compactions. " | ||
| 15575 | "Status code = %d, status = %s.", | ||
| 15576 | s.code(), s.ToString().c_str()); | ||
| 15577 | } | ||
| 15578 | 4 | } | |
| 15579 | |||
| 15580 | 5 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15581 | 5 | } | |
| 15582 | |||
| 15583 | /** | ||
| 15584 | rocksdb_set_max_bottom_pri_background_compactions_internal() changes | ||
| 15585 | the number of rocksdb background threads. | ||
| 15586 | Creating new threads may take up to a few seconds, so instead of | ||
| 15587 | calling the function at sys_var::update path where global mutex is held, | ||
| 15588 | doing at sys_var::check path so that other queries are not blocked. | ||
| 15589 | Same optimization is done for rocksdb_block_cache_size too. | ||
| 15590 | */ | ||
| 15591 | 15 | static int rocksdb_validate_max_bottom_pri_background_compactions( | |
| 15592 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 15593 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), void *var_ptr, | ||
| 15594 | struct st_mysql_value *value) { | ||
| 15595 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | assert(value != nullptr); |
| 15596 | |||
| 15597 | long long new_value; | ||
| 15598 | |||
| 15599 | /* value is NULL */ | ||
| 15600 |
2/4✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
|
15 | if (value->val_int(value, &new_value)) { |
| 15601 | ✗ | return HA_EXIT_FAILURE; | |
| 15602 | } | ||
| 15603 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | if (new_value < 0 || |
| 15604 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | new_value > ROCKSDB_MAX_BOTTOM_PRI_BACKGROUND_COMPACTIONS) { |
| 15605 | ✗ | return HA_EXIT_FAILURE; | |
| 15606 | } | ||
| 15607 |
2/4✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
15 | RDB_MUTEX_LOCK_CHECK(rdb_bottom_pri_background_compactions_resize_mutex); |
| 15608 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
|
15 | if (rocksdb_max_bottom_pri_background_compactions != new_value) { |
| 15609 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
|
14 | if (new_value == 0) { |
| 15610 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), "SET", |
| 15611 | "max_bottom_pri_background_compactions can't be changed to 0 " | ||
| 15612 | "online."); | ||
| 15613 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | RDB_MUTEX_UNLOCK_CHECK( |
| 15614 | rdb_bottom_pri_background_compactions_resize_mutex); | ||
| 15615 | 3 | return HA_EXIT_FAILURE; | |
| 15616 | } | ||
| 15617 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | rocksdb_set_max_bottom_pri_background_compactions_internal(new_value); |
| 15618 | } | ||
| 15619 | 12 | *static_cast<int64_t *>(var_ptr) = static_cast<int64_t>(new_value); | |
| 15620 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
12 | RDB_MUTEX_UNLOCK_CHECK(rdb_bottom_pri_background_compactions_resize_mutex); |
| 15621 | 12 | return HA_EXIT_SUCCESS; | |
| 15622 | } | ||
| 15623 | |||
| 15624 | 7 | static void rocksdb_set_bytes_per_sync( | |
| 15625 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 15626 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 15627 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 15628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(save != nullptr); |
| 15629 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(rocksdb_db_options != nullptr); |
| 15630 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(rocksdb_db_options->env != nullptr); |
| 15631 | |||
| 15632 | 7 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15633 | |||
| 15634 | 7 | const ulonglong new_val = *static_cast<const ulonglong *>(save); | |
| 15635 | |||
| 15636 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (rocksdb_db_options->bytes_per_sync != new_val) { |
| 15637 | 4 | rocksdb_db_options->bytes_per_sync = new_val; | |
| 15638 | rocksdb::Status s = | ||
| 15639 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
16 | rdb->SetDBOptions({{"bytes_per_sync", std::to_string(new_val)}}); |
| 15640 | |||
| 15641 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (!s.ok()) { |
| 15642 | ✗ | LogPluginErrMsg(WARNING_LEVEL, 0, | |
| 15643 | "failed to update max_background_jobs. Status code = %d, " | ||
| 15644 | "status = %s.", | ||
| 15645 | s.code(), s.ToString().c_str()); | ||
| 15646 | } | ||
| 15647 | 4 | } | |
| 15648 | |||
| 15649 | 7 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15650 | 7 | } | |
| 15651 | |||
| 15652 | 7 | static void rocksdb_set_wal_bytes_per_sync( | |
| 15653 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 15654 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), | ||
| 15655 | void *const var_ptr MY_ATTRIBUTE((__unused__)), const void *const save) { | ||
| 15656 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(save != nullptr); |
| 15657 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(rocksdb_db_options != nullptr); |
| 15658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(rocksdb_db_options->env != nullptr); |
| 15659 | |||
| 15660 | 7 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); | |
| 15661 | |||
| 15662 | 7 | const ulonglong new_val = *static_cast<const ulonglong *>(save); | |
| 15663 | |||
| 15664 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (rocksdb_db_options->wal_bytes_per_sync != new_val) { |
| 15665 | 4 | rocksdb_db_options->wal_bytes_per_sync = new_val; | |
| 15666 | rocksdb::Status s = | ||
| 15667 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
16 | rdb->SetDBOptions({{"wal_bytes_per_sync", std::to_string(new_val)}}); |
| 15668 | |||
| 15669 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (!s.ok()) { |
| 15670 | ✗ | LogPluginErrMsg(WARNING_LEVEL, 0, | |
| 15671 | "failed to update max_background_jobs. Status code = %d, " | ||
| 15672 | "status = %s.", | ||
| 15673 | s.code(), s.ToString().c_str()); | ||
| 15674 | } | ||
| 15675 | 4 | } | |
| 15676 | |||
| 15677 | 7 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15678 | 7 | } | |
| 15679 | |||
| 15680 | /* | ||
| 15681 | Validating and updating block cache size via sys_var::check path. | ||
| 15682 | SetCapacity may take seconds when reducing block cache, and | ||
| 15683 | sys_var::update holds LOCK_global_system_variables mutex, so | ||
| 15684 | updating block cache size is done at check path instead. | ||
| 15685 | */ | ||
| 15686 | 10 | static int rocksdb_validate_set_block_cache_size( | |
| 15687 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 15688 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), void *var_ptr, | ||
| 15689 | struct st_mysql_value *value) { | ||
| 15690 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | assert(value != nullptr); |
| 15691 | |||
| 15692 | long long new_value; | ||
| 15693 | |||
| 15694 | /* value is NULL */ | ||
| 15695 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (value->val_int(value, &new_value)) { |
| 15696 | ✗ | return HA_EXIT_FAILURE; | |
| 15697 | } | ||
| 15698 | |||
| 15699 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (new_value < RDB_MIN_BLOCK_CACHE_SIZE || |
| 15700 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | (uint64_t)new_value > (uint64_t)LLONG_MAX) { |
| 15701 | ✗ | return HA_EXIT_FAILURE; | |
| 15702 | } | ||
| 15703 | |||
| 15704 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | RDB_MUTEX_LOCK_CHECK(rdb_block_cache_resize_mutex); |
| 15705 | const rocksdb::BlockBasedTableOptions &table_options = | ||
| 15706 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | rdb_get_table_options(); |
| 15707 | |||
| 15708 |
5/6✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 1 times.
|
10 | if (rocksdb_block_cache_size != new_value && table_options.block_cache) { |
| 15709 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | table_options.block_cache->SetCapacity(new_value); |
| 15710 | } | ||
| 15711 | 10 | *static_cast<int64_t *>(var_ptr) = static_cast<int64_t>(new_value); | |
| 15712 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
10 | RDB_MUTEX_UNLOCK_CHECK(rdb_block_cache_resize_mutex); |
| 15713 | 10 | return HA_EXIT_SUCCESS; | |
| 15714 | } | ||
| 15715 | |||
| 15716 | 43 | static int rocksdb_validate_update_cf_options( | |
| 15717 | THD *thd MY_ATTRIBUTE((__unused__)), | ||
| 15718 | struct SYS_VAR *var MY_ATTRIBUTE((__unused__)), void *save, | ||
| 15719 | struct st_mysql_value *value) { | ||
| 15720 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 15721 | const char *str; | ||
| 15722 | int length; | ||
| 15723 | 43 | length = sizeof(buff); | |
| 15724 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | str = value->val_str(value, buff, &length); |
| 15725 | 43 | *static_cast<const char **>(save) = str; | |
| 15726 | |||
| 15727 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 37 times.
|
43 | if (str == nullptr) { |
| 15728 | 6 | return HA_EXIT_SUCCESS; | |
| 15729 | } | ||
| 15730 | |||
| 15731 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | std::stringstream output; |
| 15732 | 37 | Rdb_cf_options::Name_to_config_t option_map; | |
| 15733 | |||
| 15734 | // Basic sanity checking and parsing the options into a map. If this fails | ||
| 15735 | // then there's no point to proceed. | ||
| 15736 |
4/6✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 36 times.
|
37 | if (!Rdb_cf_options::parse_cf_options(str, &option_map, &output)) { |
| 15737 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | my_printf_error(ER_WRONG_VALUE_FOR_VAR, "%s", MYF(0), output.str().c_str()); |
| 15738 | 1 | return HA_EXIT_FAILURE; | |
| 15739 | } | ||
| 15740 | // Loop through option_map and check if all specified CFs exist. | ||
| 15741 | 36 | std::vector<const std::string *> unknown_cfs; | |
| 15742 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 36 times.
|
71 | for (const auto &option : option_map) { |
| 15743 |
3/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 28 times.
|
35 | if (!cf_manager.get_cf(option.first)) { |
| 15744 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | unknown_cfs.push_back(&(option.first)); |
| 15745 | } | ||
| 15746 | } | ||
| 15747 | |||
| 15748 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 29 times.
|
36 | if (!unknown_cfs.empty()) { |
| 15749 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | std::string err(str); |
| 15750 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | err.append(" Unknown CF: "); |
| 15751 | 7 | bool first = true; | |
| 15752 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | for (const auto cf : unknown_cfs) { |
| 15753 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (first) |
| 15754 | 7 | first = false; | |
| 15755 | else | ||
| 15756 | ✗ | err.append(", "); | |
| 15757 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | err.append(*cf); |
| 15758 | } | ||
| 15759 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "rocksdb_update_cf_options", |
| 15760 | err.c_str()); | ||
| 15761 | 7 | return HA_EXIT_FAILURE; | |
| 15762 | 7 | } | |
| 15763 | 29 | return HA_EXIT_SUCCESS; | |
| 15764 | 37 | } | |
| 15765 | |||
| 15766 | 35 | static void rocksdb_set_update_cf_options( | |
| 15767 | THD *const thd MY_ATTRIBUTE((__unused__)), | ||
| 15768 | struct SYS_VAR *const var MY_ATTRIBUTE((__unused__)), void *const var_ptr, | ||
| 15769 | const void *const save) { | ||
| 15770 | 35 | const char *const val = *static_cast<const char *const *>(save); | |
| 15771 | |||
| 15772 |
2/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
|
35 | RDB_MUTEX_LOCK_CHECK(rdb_sysvars_mutex); |
| 15773 | |||
| 15774 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 29 times.
|
35 | if (!val) { |
| 15775 | 6 | *reinterpret_cast<char **>(var_ptr) = nullptr; | |
| 15776 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); |
| 15777 | 6 | return; | |
| 15778 | } | ||
| 15779 | |||
| 15780 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | assert(val != nullptr); |
| 15781 | |||
| 15782 | // Reset the pointers regardless of how much success we had with updating | ||
| 15783 | // the CF options. This will results in consistent behavior and avoids | ||
| 15784 | // dealing with cases when only a subset of CF-s was successfully updated. | ||
| 15785 | 29 | *static_cast<const char **>(var_ptr) = | |
| 15786 | 29 | *static_cast<const char *const *>(save); | |
| 15787 | |||
| 15788 | // Do the real work of applying the changes. | ||
| 15789 | 29 | Rdb_cf_options::Name_to_config_t option_map; | |
| 15790 | |||
| 15791 | // This should never fail, because of rocksdb_validate_update_cf_options | ||
| 15792 |
3/6✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 29 times.
|
29 | if (!Rdb_cf_options::parse_cf_options(val, &option_map)) { |
| 15793 | ✗ | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); | |
| 15794 | ✗ | return; | |
| 15795 | } | ||
| 15796 | |||
| 15797 | // For each CF we have, see if we need to update any settings. | ||
| 15798 |
3/4✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 29 times.
|
187 | for (const auto &cf_name : cf_manager.get_cf_names()) { |
| 15799 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
|
158 | assert(!cf_name.empty()); |
| 15800 | |||
| 15801 | std::shared_ptr<rocksdb::ColumnFamilyHandle> cfh = | ||
| 15802 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | cf_manager.get_cf(cf_name); |
| 15803 | |||
| 15804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
|
158 | if (!cfh) { |
| 15805 | ✗ | LogPluginErrMsg( | |
| 15806 | INFORMATION_LEVEL, 0, | ||
| 15807 | "Skip updating options for cf %s because the cf has been dropped.", | ||
| 15808 | cf_name.c_str()); | ||
| 15809 | ✗ | continue; | |
| 15810 | } | ||
| 15811 | |||
| 15812 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | const auto it = option_map.find(cf_name); |
| 15813 |
6/10✓ Branch 0 taken 27 times.
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 131 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 131 times.
✓ Branch 7 taken 27 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
158 | std::string per_cf_options = (it != option_map.end()) ? it->second : ""; |
| 15814 | |||
| 15815 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 131 times.
|
158 | if (!per_cf_options.empty()) { |
| 15816 | 27 | Rdb_cf_options::Name_to_config_t opt_map; | |
| 15817 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | rocksdb::Status s = rocksdb::StringToMap(per_cf_options, &opt_map); |
| 15818 | |||
| 15819 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
|
27 | if (s != rocksdb::Status::OK()) { |
| 15820 | ✗ | LogPluginErrMsg( | |
| 15821 | WARNING_LEVEL, 0, | ||
| 15822 | "failed to convert the options for column family '%s' to a map. %s", | ||
| 15823 | cf_name.c_str(), s.ToString().c_str()); | ||
| 15824 | } else { | ||
| 15825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | assert(rdb != nullptr); |
| 15826 | |||
| 15827 | // Finally we can apply the options. | ||
| 15828 | // If cf_manager.drop_cf() has been called at this point, SetOptions() | ||
| 15829 | // will still succeed. The options data will only be cleared when | ||
| 15830 | // the CF handle object is destroyed. | ||
| 15831 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | s = rdb->SetOptions(cfh.get(), opt_map); |
| 15832 | |||
| 15833 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
|
27 | if (s != rocksdb::Status::OK()) { |
| 15834 | ✗ | LogPluginErrMsg( | |
| 15835 | WARNING_LEVEL, 0, | ||
| 15836 | "failed to apply the options for column family '%s'. %s", | ||
| 15837 | cf_name.c_str(), s.ToString().c_str()); | ||
| 15838 | } else { | ||
| 15839 |
9/18✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 27 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 27 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 27 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 27 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 27 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 27 times.
✗ Branch 17 not taken.
|
27 | LogPluginErrMsg( |
| 15840 | INFORMATION_LEVEL, 0, | ||
| 15841 | "options for column family '%s' have been successfully updated.", | ||
| 15842 | cf_name.c_str()); | ||
| 15843 | |||
| 15844 | // Make sure that data is internally consistent as well and update | ||
| 15845 | // the CF options. This is necessary also to make sure that the CF | ||
| 15846 | // options will be correctly reflected in the relevant table: | ||
| 15847 | // ROCKSDB_CF_OPTIONS in INFORMATION_SCHEMA. | ||
| 15848 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | rocksdb::ColumnFamilyOptions cf_options = rdb->GetOptions(cfh.get()); |
| 15849 | 27 | std::string updated_options; | |
| 15850 | |||
| 15851 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
54 | s = rocksdb::GetStringFromColumnFamilyOptions(&updated_options, |
| 15852 | 27 | cf_options); | |
| 15853 | |||
| 15854 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
|
27 | assert(s == rocksdb::Status::OK()); |
| 15855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | assert(!updated_options.empty()); |
| 15856 | |||
| 15857 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | cf_manager.update_options_map(cf_name, updated_options); |
| 15858 | 27 | } | |
| 15859 | } | ||
| 15860 | 27 | } | |
| 15861 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
187 | } |
| 15862 | |||
| 15863 | // Our caller (`plugin_var_memalloc_global_update`) will call `my_free` to | ||
| 15864 | // free up resources used before. | ||
| 15865 | |||
| 15866 |
2/4✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
|
29 | RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); |
| 15867 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | } |
| 15868 | |||
| 15869 | 26416 | void rdb_queue_save_stats_request() { rdb_bg_thread.request_save_stats(); } | |
| 15870 | |||
| 15871 | #if defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 15872 | 5105 | void ha_rocksdb::rpl_before_delete_rows() { | |
| 15873 |
1/2✓ Branch 0 taken 5105 times.
✗ Branch 1 not taken.
|
5105 | DBUG_ENTER_FUNC(); |
| 15874 | |||
| 15875 | 5105 | m_in_rpl_delete_rows = true; | |
| 15876 | |||
| 15877 |
1/2✓ Branch 0 taken 5105 times.
✗ Branch 1 not taken.
|
10210 | DBUG_VOID_RETURN; |
| 15878 | } | ||
| 15879 | |||
| 15880 | 5105 | void ha_rocksdb::rpl_after_delete_rows() { | |
| 15881 |
1/2✓ Branch 0 taken 5105 times.
✗ Branch 1 not taken.
|
5105 | DBUG_ENTER_FUNC(); |
| 15882 | |||
| 15883 | 5105 | m_in_rpl_delete_rows = false; | |
| 15884 | |||
| 15885 |
1/2✓ Branch 0 taken 5105 times.
✗ Branch 1 not taken.
|
10210 | DBUG_VOID_RETURN; |
| 15886 | } | ||
| 15887 | |||
| 15888 | 6825 | void ha_rocksdb::rpl_before_update_rows() { | |
| 15889 |
1/2✓ Branch 0 taken 6825 times.
✗ Branch 1 not taken.
|
6825 | DBUG_ENTER_FUNC(); |
| 15890 | |||
| 15891 | 6825 | m_in_rpl_update_rows = true; | |
| 15892 | |||
| 15893 |
1/2✓ Branch 0 taken 6825 times.
✗ Branch 1 not taken.
|
13650 | DBUG_VOID_RETURN; |
| 15894 | } | ||
| 15895 | |||
| 15896 | 6825 | void ha_rocksdb::rpl_after_update_rows() { | |
| 15897 |
1/2✓ Branch 0 taken 6825 times.
✗ Branch 1 not taken.
|
6825 | DBUG_ENTER_FUNC(); |
| 15898 | |||
| 15899 | 6825 | m_in_rpl_update_rows = false; | |
| 15900 | |||
| 15901 |
1/2✓ Branch 0 taken 6825 times.
✗ Branch 1 not taken.
|
13650 | DBUG_VOID_RETURN; |
| 15902 | } | ||
| 15903 | |||
| 15904 | 9770 | bool ha_rocksdb::rpl_lookup_rows() { return !use_read_free_rpl(); } | |
| 15905 | |||
| 15906 | 117067 | bool ha_rocksdb::is_read_free_rpl_table() const { | |
| 15907 | #if 1 // Percona Server disabled rocksdb_read_free_rpl_tables as it's dangerous | ||
| 15908 | // to use | ||
| 15909 | 117067 | return true; | |
| 15910 | #else | ||
| 15911 | return table->s && m_tbl_def->m_is_read_free_rpl_table; | ||
| 15912 | #endif | ||
| 15913 | } | ||
| 15914 | |||
| 15915 | /** | ||
| 15916 | @brief | ||
| 15917 | Read Free Replication can be used or not. Returning true means | ||
| 15918 | Read Free Replication can be used. | ||
| 15919 | */ | ||
| 15920 | 20360039 | bool ha_rocksdb::use_read_free_rpl() const { | |
| 15921 |
1/2✓ Branch 0 taken 20579339 times.
✗ Branch 1 not taken.
|
20360039 | DBUG_ENTER_FUNC(); |
| 15922 | |||
| 15923 |
9/12✓ Branch 0 taken 20590688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 117327 times.
✓ Branch 3 taken 20473361 times.
✓ Branch 4 taken 117067 times.
✓ Branch 5 taken 260 times.
✓ Branch 6 taken 117067 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 117067 times.
✓ Branch 10 taken 20436108 times.
✓ Branch 11 taken 154580 times.
|
20579339 | if (!ha_thd()->rli_slave || table->triggers || !is_read_free_rpl_table()) { |
| 15924 |
1/2✓ Branch 0 taken 20474861 times.
✗ Branch 1 not taken.
|
20436108 | DBUG_RETURN(false); |
| 15925 | } | ||
| 15926 | |||
| 15927 |
2/4✓ Branch 0 taken 117067 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37513 times.
|
154580 | switch (rocksdb_read_free_rpl) { |
| 15928 | 117067 | case read_free_rpl_type::OFF: | |
| 15929 |
1/2✓ Branch 0 taken 117067 times.
✗ Branch 1 not taken.
|
117067 | DBUG_RETURN(false); |
| 15930 | ✗ | case read_free_rpl_type::PK_ONLY: | |
| 15931 | ✗ | DBUG_RETURN(!has_hidden_pk(table) && table->s->keys == 1); | |
| 15932 | ✗ | case read_free_rpl_type::PK_SK: | |
| 15933 | ✗ | DBUG_RETURN(!has_hidden_pk(table)); | |
| 15934 | } | ||
| 15935 | |||
| 15936 | 37513 | assert(false); | |
| 15937 | DBUG_RETURN(false); | ||
| 15938 | } | ||
| 15939 | #endif // defined(ROCKSDB_INCLUDE_RFR) && ROCKSDB_INCLUDE_RFR | ||
| 15940 | |||
| 15941 | 21292 | uchar *blob_buffer::get_blob_buffer(uint current_size) { | |
| 15942 | 21292 | auto output = m_blob_buffer_current; | |
| 15943 | 21292 | m_blob_buffer_current = m_blob_buffer_current + current_size; | |
| 15944 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21292 times.
|
21292 | assert((m_blob_buffer_current - m_blob_buffer_start) <= |
| 15945 | m_total_blob_buffer_allocated); | ||
| 15946 | 21292 | return output; | |
| 15947 | } | ||
| 15948 | |||
| 15949 | 37861 | bool blob_buffer::reset_blob_buffer(uint total_size) { | |
| 15950 |
2/2✓ Branch 0 taken 3682 times.
✓ Branch 1 taken 34179 times.
|
37861 | if (m_blob_buffer_start == nullptr) { |
| 15951 | 3682 | m_blob_buffer_start = reinterpret_cast<uchar *>( | |
| 15952 | 3682 | my_malloc(PSI_NOT_INSTRUMENTED, total_size, MYF(0))); | |
| 15953 | 3682 | m_total_blob_buffer_allocated = total_size; | |
| 15954 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34179 times.
|
34179 | } else if (m_total_blob_buffer_allocated < total_size) { |
| 15955 | ✗ | my_free(m_blob_buffer_start); | |
| 15956 | ✗ | m_blob_buffer_start = reinterpret_cast<uchar *>( | |
| 15957 | ✗ | my_malloc(PSI_NOT_INSTRUMENTED, total_size, MYF(0))); | |
| 15958 | ✗ | m_total_blob_buffer_allocated = total_size; | |
| 15959 | } | ||
| 15960 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37861 times.
|
37861 | if (!m_blob_buffer_start) return true; |
| 15961 | 37861 | m_blob_buffer_current = m_blob_buffer_start; | |
| 15962 | 37861 | return false; | |
| 15963 | } | ||
| 15964 | |||
| 15965 | 4186484 | void blob_buffer::release_blob_buffer() { | |
| 15966 |
2/2✓ Branch 0 taken 3682 times.
✓ Branch 1 taken 4182802 times.
|
4186484 | if (m_blob_buffer_start != nullptr) { |
| 15967 | 3682 | my_free(m_blob_buffer_start); | |
| 15968 | 3682 | m_blob_buffer_start = nullptr; | |
| 15969 | } | ||
| 15970 | 4186484 | } | |
| 15971 | |||
| 15972 | 385107 | double ha_rocksdb::read_time(uint index, uint ranges, ha_rows rows) { | |
| 15973 |
1/2✓ Branch 0 taken 385107 times.
✗ Branch 1 not taken.
|
385107 | DBUG_ENTER_FUNC(); |
| 15974 | |||
| 15975 |
2/2✓ Branch 0 taken 71136 times.
✓ Branch 1 taken 313971 times.
|
385107 | if (index != table->s->primary_key) { |
| 15976 | /* Non covering index range scan */ | ||
| 15977 |
1/2✓ Branch 0 taken 71136 times.
✗ Branch 1 not taken.
|
71136 | DBUG_RETURN(handler::read_time(index, ranges, rows)); |
| 15978 | } | ||
| 15979 | |||
| 15980 |
1/2✓ Branch 0 taken 313971 times.
✗ Branch 1 not taken.
|
313971 | DBUG_RETURN((rows / 20.0) + 1); |
| 15981 | } | ||
| 15982 | |||
| 15983 | 3431 | void ha_rocksdb::print_error(int error, myf errflag) { | |
| 15984 |
3/3✓ Branch 0 taken 64 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 3105 times.
|
3431 | switch (error) { |
| 15985 | 64 | case HA_ERR_ROCKSDB_STATUS_BUSY: | |
| 15986 | 64 | handler::print_error(HA_ERR_LOCK_DEADLOCK, errflag); | |
| 15987 | 64 | break; | |
| 15988 | 262 | case HA_ERR_LOCK_WAIT_TIMEOUT: | |
| 15989 |
5/6✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 256 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 256 times.
|
262 | if (error == HA_ERR_LOCK_WAIT_TIMEOUT && my_core::thd_killed(ha_thd())) { |
| 15990 | 6 | my_error(ER_QUERY_TIMEOUT, errflag, | |
| 15991 | 6 | table_share->table_name.str /*, error*/); | |
| 15992 | } else { | ||
| 15993 | 256 | handler::print_error(error, errflag); | |
| 15994 | } | ||
| 15995 | 262 | break; | |
| 15996 | 3105 | default: | |
| 15997 | 3105 | handler::print_error(error, errflag); | |
| 15998 | 3105 | break; | |
| 15999 | } | ||
| 16000 | 3431 | } | |
| 16001 | |||
| 16002 | 932 | std::string rdb_corruption_marker_file_name() { | |
| 16003 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | std::string ret(rocksdb_datadir); |
| 16004 |
1/2✓ Branch 0 taken 932 times.
✗ Branch 1 not taken.
|
932 | ret.append("/ROCKSDB_CORRUPTED"); |
| 16005 | 932 | return ret; | |
| 16006 | } | ||
| 16007 | |||
| 16008 | 932 | rocksdb::DBOptions *get_rocksdb_db_options() { | |
| 16009 | 932 | return rocksdb_db_options.get(); | |
| 16010 | } | ||
| 16011 | |||
| 16012 | 7 | static void rocksdb_max_compaction_history_update( | |
| 16013 | my_core::THD *const /* unused */, my_core::SYS_VAR *const /* unused */, | ||
| 16014 | void *const var_ptr, const void *const save) { | ||
| 16015 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | assert(rdb != nullptr); |
| 16016 | |||
| 16017 | 7 | uint64_t val = *static_cast<uint64_t *>(var_ptr) = | |
| 16018 | 7 | *static_cast<const uint64_t *>(save); | |
| 16019 | 7 | compaction_stats.resize_history(val); | |
| 16020 | 7 | } | |
| 16021 | |||
| 16022 | 909 | void Rdb_compaction_stats::resize_history(size_t max_history_len) { | |
| 16023 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | std::lock_guard<std::mutex> guard(m_mutex); |
| 16024 | 909 | m_max_history_len = max_history_len; | |
| 16025 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 908 times.
|
909 | if (m_history.size() > m_max_history_len) { |
| 16026 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | m_history.erase(m_history.begin(), |
| 16027 | 2 | m_history.begin() + (m_history.size() - m_max_history_len)); | |
| 16028 | } | ||
| 16029 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
|
909 | assert(m_history.size() <= m_max_history_len); |
| 16030 | 909 | } | |
| 16031 | |||
| 16032 | std::vector<Rdb_compaction_stats_record> | ||
| 16033 | ✗ | Rdb_compaction_stats::get_current_stats() { | |
| 16034 | ✗ | std::lock_guard<std::mutex> guard(m_mutex); | |
| 16035 | ✗ | std::vector<Rdb_compaction_stats_record> res; | |
| 16036 | ✗ | res.reserve(m_tid_to_pending_compaction.size()); | |
| 16037 | ✗ | for (const auto &tid_and_pending_compaction : m_tid_to_pending_compaction) { | |
| 16038 | ✗ | res.push_back(tid_and_pending_compaction.second); | |
| 16039 | } | ||
| 16040 | ✗ | return res; | |
| 16041 | } | ||
| 16042 | |||
| 16043 | std::vector<Rdb_compaction_stats_record> | ||
| 16044 | ✗ | Rdb_compaction_stats::get_recent_history() { | |
| 16045 | ✗ | std::lock_guard<std::mutex> guard(m_mutex); | |
| 16046 | ✗ | std::vector<Rdb_compaction_stats_record> res; | |
| 16047 | ✗ | res.reserve(m_history.size()); | |
| 16048 | ✗ | for (const auto &record : m_history) { | |
| 16049 | ✗ | res.push_back(record); | |
| 16050 | } | ||
| 16051 | ✗ | return res; | |
| 16052 | } | ||
| 16053 | |||
| 16054 | 18641 | void Rdb_compaction_stats::record_start(rocksdb::CompactionJobInfo info) { | |
| 16055 |
1/2✓ Branch 0 taken 18641 times.
✗ Branch 1 not taken.
|
18641 | std::lock_guard<std::mutex> guard(m_mutex); |
| 16056 | 18641 | time_t start_timestamp = time(nullptr /* tloc */); | |
| 16057 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18641 times.
|
18641 | assert(start_timestamp != static_cast<time_t>(-1)); |
| 16058 | |||
| 16059 |
2/4✓ Branch 0 taken 18641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18641 times.
✗ Branch 3 not taken.
|
37282 | m_tid_to_pending_compaction[info.thread_id] = Rdb_compaction_stats_record{ |
| 16060 | start_timestamp, static_cast<time_t>(-1) /* end_timestamp */, | ||
| 16061 |
1/2✓ Branch 0 taken 18641 times.
✗ Branch 1 not taken.
|
37282 | std::move(info)}; |
| 16062 | 18641 | } | |
| 16063 | |||
| 16064 | 18338 | void Rdb_compaction_stats::record_end(rocksdb::CompactionJobInfo info) { | |
| 16065 |
1/2✓ Branch 0 taken 18338 times.
✗ Branch 1 not taken.
|
18338 | std::lock_guard<std::mutex> guard(m_mutex); |
| 16066 | auto tid_to_pending_compaction_iter = | ||
| 16067 |
1/2✓ Branch 0 taken 18338 times.
✗ Branch 1 not taken.
|
18338 | m_tid_to_pending_compaction.find(info.thread_id); |
| 16068 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18338 times.
|
18338 | assert(tid_to_pending_compaction_iter != m_tid_to_pending_compaction.end()); |
| 16069 |
1/2✓ Branch 0 taken 18338 times.
✗ Branch 1 not taken.
|
18338 | Rdb_compaction_stats_record record; |
| 16070 |
1/2✓ Branch 0 taken 18338 times.
✗ Branch 1 not taken.
|
18338 | if (tid_to_pending_compaction_iter != m_tid_to_pending_compaction.end()) { |
| 16071 | 18338 | record.start_timestamp = | |
| 16072 | 18338 | tid_to_pending_compaction_iter->second.start_timestamp; | |
| 16073 |
1/2✓ Branch 0 taken 18338 times.
✗ Branch 1 not taken.
|
18338 | m_tid_to_pending_compaction.erase(tid_to_pending_compaction_iter); |
| 16074 | } else { | ||
| 16075 | ✗ | record.start_timestamp = static_cast<time_t>(-1); | |
| 16076 | } | ||
| 16077 |
2/2✓ Branch 0 taken 164 times.
✓ Branch 1 taken 18174 times.
|
18338 | if (m_max_history_len == 0) { |
| 16078 | 164 | return; | |
| 16079 | } | ||
| 16080 |
2/2✓ Branch 0 taken 9309 times.
✓ Branch 1 taken 8865 times.
|
18174 | if (m_history.size() == m_max_history_len) { |
| 16081 | 9309 | m_history.pop_front(); | |
| 16082 | } | ||
| 16083 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18174 times.
|
18174 | assert(m_history.size() < m_max_history_len); |
| 16084 | 18174 | record.end_timestamp = time(nullptr /* tloc */); | |
| 16085 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18174 times.
|
18174 | assert(record.end_timestamp != static_cast<time_t>(-1)); |
| 16086 |
1/2✓ Branch 0 taken 18174 times.
✗ Branch 1 not taken.
|
18174 | record.info = std::move(info); |
| 16087 |
1/2✓ Branch 0 taken 18174 times.
✗ Branch 1 not taken.
|
18174 | m_history.emplace_back(std::move(record)); |
| 16088 |
4/4✓ Branch 0 taken 18174 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 18174 times.
✓ Branch 3 taken 164 times.
|
18502 | } |
| 16089 | |||
| 16090 | 756 | unsigned long long get_partial_index_sort_max_mem(THD *thd) { | |
| 16091 | 756 | return THDVAR(thd, partial_index_sort_max_mem); | |
| 16092 | } | ||
| 16093 | |||
| 16094 | ✗ | const rocksdb::ReadOptions &rdb_tx_acquire_snapshot(Rdb_transaction *tx) { | |
| 16095 | ✗ | tx->acquire_snapshot(true); | |
| 16096 | ✗ | return tx->m_read_opts; | |
| 16097 | } | ||
| 16098 | |||
| 16099 | 263036 | rocksdb::Iterator *rdb_tx_get_iterator( | |
| 16100 | THD *thd, rocksdb::ColumnFamilyHandle *const cf, bool skip_bloom_filter, | ||
| 16101 | const rocksdb::Slice &eq_cond_lower_bound, | ||
| 16102 | const rocksdb::Slice &eq_cond_upper_bound, | ||
| 16103 | const rocksdb::Snapshot **snapshot, bool read_current, | ||
| 16104 | bool create_snapshot) { | ||
| 16105 |
2/2✓ Branch 0 taken 138 times.
✓ Branch 1 taken 262898 times.
|
263036 | if (commit_in_the_middle(thd)) { |
| 16106 |
2/4✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 138 times.
✗ Branch 3 not taken.
|
138 | assert(snapshot && *snapshot == nullptr); |
| 16107 |
1/2✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
|
138 | if (snapshot) { |
| 16108 |
1/2✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
|
138 | *snapshot = rdb->GetSnapshot(); |
| 16109 |
1/2✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
|
138 | auto read_opts = rocksdb::ReadOptions(); |
| 16110 | // TODO(mung): set based on WHERE conditions | ||
| 16111 | 138 | read_opts.total_order_seek = true; | |
| 16112 | 138 | read_opts.snapshot = *snapshot; | |
| 16113 |
1/2✓ Branch 0 taken 138 times.
✗ Branch 1 not taken.
|
138 | return rdb->NewIterator(read_opts, cf); |
| 16114 | 138 | } else { | |
| 16115 | ✗ | return nullptr; | |
| 16116 | } | ||
| 16117 | } else { | ||
| 16118 | 262898 | Rdb_transaction *tx = get_tx_from_thd(thd); | |
| 16119 | 262898 | return tx->get_iterator(cf, skip_bloom_filter, eq_cond_lower_bound, | |
| 16120 | 262898 | eq_cond_upper_bound, read_current, create_snapshot); | |
| 16121 | } | ||
| 16122 | } | ||
| 16123 | |||
| 16124 | ✗ | bool rdb_tx_started(Rdb_transaction *tx) { return tx->is_tx_started(); } | |
| 16125 | |||
| 16126 | 12100520 | rocksdb::Status rdb_tx_get(Rdb_transaction *tx, | |
| 16127 | rocksdb::ColumnFamilyHandle *const column_family, | ||
| 16128 | const rocksdb::Slice &key, | ||
| 16129 | rocksdb::PinnableSlice *const value) { | ||
| 16130 | 12100520 | return tx->get(column_family, key, value); | |
| 16131 | } | ||
| 16132 | |||
| 16133 | 12579318 | rocksdb::Status rdb_tx_get_for_update(Rdb_transaction *tx, | |
| 16134 | const Rdb_key_def &kd, | ||
| 16135 | const rocksdb::Slice &key, | ||
| 16136 | rocksdb::PinnableSlice *const value, | ||
| 16137 | bool exclusive, bool skip_wait) { | ||
| 16138 | bool do_validate = | ||
| 16139 | 12579318 | my_core::thd_tx_isolation(tx->get_thd()) > ISO_READ_COMMITTED; | |
| 16140 | rocksdb::Status s = | ||
| 16141 | 12590182 | tx->get_for_update(kd, key, value, exclusive, do_validate, skip_wait); | |
| 16142 | |||
| 16143 | #ifndef NDEBUG | ||
| 16144 | 12639530 | ++rocksdb_num_get_for_update_calls; | |
| 16145 | #endif | ||
| 16146 | 12720778 | return s; | |
| 16147 | } | ||
| 16148 | |||
| 16149 | 564 | void rdb_tx_release_lock(Rdb_transaction *tx, const Rdb_key_def &kd, | |
| 16150 | const rocksdb::Slice &key, bool force) { | ||
| 16151 |
2/4✓ Branch 0 taken 564 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 564 times.
✗ Branch 3 not taken.
|
564 | tx->release_lock(kd, std::string(key.data(), key.size()), force); |
| 16152 | 564 | } | |
| 16153 | |||
| 16154 | 437 | int rdb_tx_set_status_error(Rdb_transaction *tx, const rocksdb::Status &s, | |
| 16155 | const Rdb_key_def &kd, | ||
| 16156 | const Rdb_tbl_def *const tbl_def) { | ||
| 16157 | 437 | return tx->set_status_error(tx->get_thd(), s, kd, tbl_def); | |
| 16158 | } | ||
| 16159 | |||
| 16160 | 3 | static bool parse_fault_injection_file_type(const std::string &type_str, | |
| 16161 | rocksdb::FileType *type) { | ||
| 16162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (type_str == "kWalFile") { |
| 16163 | ✗ | *type = rocksdb::FileType::kWalFile; | |
| 16164 | ✗ | return false; | |
| 16165 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | } else if (type_str == "kTableFile") { |
| 16166 | 3 | *type = rocksdb::FileType::kTableFile; | |
| 16167 | 3 | return false; | |
| 16168 | ✗ | } else if (type_str == "kDescriptorFile") { | |
| 16169 | ✗ | *type = rocksdb::FileType::kDescriptorFile; | |
| 16170 | ✗ | return false; | |
| 16171 | } | ||
| 16172 | ✗ | return true; | |
| 16173 | } | ||
| 16174 | |||
| 16175 | 3 | static bool parse_fault_injection_params( | |
| 16176 | bool *retryable, uint32_t *failure_ratio, | ||
| 16177 | std::vector<rocksdb::FileType> *types) { | ||
| 16178 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rapidjson::Document doc; |
| 16179 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | rapidjson::ParseResult ok = doc.Parse(opt_rocksdb_fault_injection_options); |
| 16180 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (!ok) { |
| 16181 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 16182 | "Parse error (errcode=%d offset=%lu) " | ||
| 16183 | "rocksdb_fault_injection_options=%s", | ||
| 16184 | ok.Code(), ok.Offset(), | ||
| 16185 | opt_rocksdb_fault_injection_options); | ||
| 16186 | ✗ | return true; | |
| 16187 | } | ||
| 16188 | |||
| 16189 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | auto retry_it = doc.FindMember("retry"); |
| 16190 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | auto fr_it = doc.FindMember("failure_ratio"); |
| 16191 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | auto ft_it = doc.FindMember("filetypes"); |
| 16192 | |||
| 16193 |
5/10✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
|
6 | if (retry_it == doc.MemberEnd() || fr_it == doc.MemberEnd() || |
| 16194 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
6 | ft_it == doc.MemberEnd()) { |
| 16195 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 16196 | "rocksdb_fault_injection_options=%s schema not valid", | ||
| 16197 | opt_rocksdb_fault_injection_options); | ||
| 16198 | ✗ | return true; | |
| 16199 | } | ||
| 16200 | |||
| 16201 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
6 | if (!retry_it->value.IsBool() || !fr_it->value.IsInt() || |
| 16202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | !ft_it->value.IsArray()) { |
| 16203 | // NO_LINT_DEBUG | ||
| 16204 | ✗ | LogPluginErrMsg( | |
| 16205 | ERROR_LEVEL, 0, | ||
| 16206 | "rocksdb_fault_injection_options=%s schema not valid (wrong " | ||
| 16207 | "types)", | ||
| 16208 | opt_rocksdb_fault_injection_options); | ||
| 16209 | ✗ | return true; | |
| 16210 | } | ||
| 16211 | |||
| 16212 | 3 | *retryable = retry_it->value.GetBool(); | |
| 16213 | 3 | *failure_ratio = fr_it->value.GetInt(); | |
| 16214 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (rapidjson::SizeType i = 0; i < ft_it->value.Size(); i++) { |
| 16215 | rocksdb::FileType type; | ||
| 16216 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | if (!ft_it->value[i].IsString() || |
| 16217 |
8/20✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
6 | parse_fault_injection_file_type(ft_it->value[i].GetString(), &type)) { |
| 16218 | ✗ | LogPluginErrMsg(ERROR_LEVEL, 0, | |
| 16219 | "Wrong filetype = %s to " | ||
| 16220 | "rocksdb_fault_injection_options=%s", | ||
| 16221 | ft_it->value[i].IsString() ? ft_it->value[i].GetString() | ||
| 16222 | : "(wrong type)", | ||
| 16223 | opt_rocksdb_fault_injection_options); | ||
| 16224 | ✗ | return true; | |
| 16225 | } | ||
| 16226 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | types->push_back(type); |
| 16227 | } | ||
| 16228 | |||
| 16229 | 3 | return false; | |
| 16230 | 3 | } | |
| 16231 | |||
| 16232 | } // namespace myrocks | ||
| 16233 | |||
| 16234 | /* | ||
| 16235 | Register the storage engine plugin outside of myrocks namespace | ||
| 16236 | so that mysql_declare_plugin does not get confused when it does | ||
| 16237 | its name generation. | ||
| 16238 | */ | ||
| 16239 | |||
| 16240 | struct st_mysql_storage_engine rocksdb_storage_engine = { | ||
| 16241 | MYSQL_HANDLERTON_INTERFACE_VERSION}; | ||
| 16242 | |||
| 16243 | mysql_declare_plugin(rocksdb_se){ | ||
| 16244 | MYSQL_STORAGE_ENGINE_PLUGIN, /* Plugin Type */ | ||
| 16245 | &rocksdb_storage_engine, /* Plugin Descriptor */ | ||
| 16246 | "ROCKSDB", /* Plugin Name */ | ||
| 16247 | "Monty Program Ab", /* Plugin Author */ | ||
| 16248 | "RocksDB storage engine", /* Plugin Description */ | ||
| 16249 | PLUGIN_LICENSE_GPL, /* Plugin Licence */ | ||
| 16250 | myrocks::rocksdb_init_func, /* Plugin Entry Point */ | ||
| 16251 | nullptr, /* Plugin Check Uninstall */ | ||
| 16252 | myrocks::rocksdb_done_func, /* Plugin Deinitializer */ | ||
| 16253 | 0x0001, /* version number (0.1) */ | ||
| 16254 | myrocks::rocksdb_status_vars, /* status variables */ | ||
| 16255 | myrocks::rocksdb_system_variables, /* system variables */ | ||
| 16256 | nullptr, /* config options */ | ||
| 16257 | 0, /* flags */ | ||
| 16258 | }, | ||
| 16259 | myrocks::rdb_i_s_cfstats, myrocks::rdb_i_s_dbstats, | ||
| 16260 | myrocks::rdb_i_s_perf_context, myrocks::rdb_i_s_perf_context_global, | ||
| 16261 | myrocks::rdb_i_s_cfoptions, myrocks::rdb_i_s_compact_stats, | ||
| 16262 | myrocks::rdb_i_s_active_compact_stats, myrocks::rdb_i_s_compact_history, | ||
| 16263 | myrocks::rdb_i_s_global_info, myrocks::rdb_i_s_ddl, | ||
| 16264 | myrocks::rdb_i_s_sst_props, myrocks::rdb_i_s_index_file_map, | ||
| 16265 | myrocks::rdb_i_s_lock_info, myrocks::rdb_i_s_trx_info, | ||
| 16266 | myrocks::rdb_i_s_deadlock_info mysql_declare_plugin_end; | ||
| 16267 |